diff --git a/features/options/routed/help.feature b/features/options/routed/help.feature index d9c252a12..34c6ee2a8 100644 --- a/features/options/routed/help.feature +++ b/features/options/routed/help.feature @@ -25,9 +25,11 @@ Feature: osrm-routed command line options: help And stdout should contain "--port" And stdout should contain "--threads" And stdout should contain "--shared-memory" + And stdout should contain "--max-viaroute-size" + And stdout should contain "--max-trip-size" And stdout should contain "--max-table-size" And stdout should contain "--max-matching-size" - And stdout should contain 27 lines + And stdout should contain 30 lines And it should exit with code 0 Scenario: osrm-routed - Help, short @@ -51,9 +53,11 @@ Feature: osrm-routed command line options: help And stdout should contain "--port" And stdout should contain "--threads" And stdout should contain "--shared-memory" + And stdout should contain "--max-viaroute-size" + And stdout should contain "--max-trip-size" And stdout should contain "--max-table-size" And stdout should contain "--max-matching-size" - And stdout should contain 27 lines + And stdout should contain 30 lines And it should exit with code 0 Scenario: osrm-routed - Help, long @@ -77,7 +81,9 @@ Feature: osrm-routed command line options: help And stdout should contain "--port" And stdout should contain "--threads" And stdout should contain "--shared-memory" + And stdout should contain "--max-trip-size" + And stdout should contain "--max-table-size" And stdout should contain "--max-table-size" And stdout should contain "--max-matching-size" - And stdout should contain 27 lines + And stdout should contain 30 lines And it should exit with code 0 diff --git a/features/step_definitions/nearest.rb b/features/step_definitions/nearest.rb index f0e5dad08..b0b5f94b8 100644 --- a/features/step_definitions/nearest.rb +++ b/features/step_definitions/nearest.rb @@ -12,7 +12,7 @@ When /^I request nearest I should get$/ do |table| response = request_nearest in_node, @query_params if response.code == "200" && response.body.empty? == false json = JSON.parse response.body - if json['status'] == 0 + if json['status'] == 200 coord = json['mapped_coordinate'] end end diff --git a/features/step_definitions/routability.rb b/features/step_definitions/routability.rb index daafe5fd3..6b5134c8c 100644 --- a/features/step_definitions/routability.rb +++ b/features/step_definitions/routability.rb @@ -8,8 +8,8 @@ def test_routability_row i r[:query] = @query r[:json] = JSON.parse(r[:response].body) - r[:status] = route_status r[:response] - if r[:status].empty? == false + r[:status] = (route_status r[:response]) == 200 ? 'x' : nil + if r[:status] then r[:route] = way_list r[:json]['route_instructions'] if r[:route]=="w#{i}" diff --git a/features/step_definitions/routing.rb b/features/step_definitions/routing.rb index de585b06e..f1e9590d7 100644 --- a/features/step_definitions/routing.rb +++ b/features/step_definitions/routing.rb @@ -56,7 +56,7 @@ When /^I route I should get$/ do |table| end if response.body.empty? == false - if json['status'] == 0 + if json['status'] == 200 instructions = way_list json['route_instructions'] bearings = bearing_list json['route_instructions'] compasses = compass_list json['route_instructions'] @@ -77,66 +77,64 @@ When /^I route I should get$/ do |table| got['#'] = row['#'] # copy value so it always match end - if response.code == "200" - if table.headers.include? 'start' - got['start'] = instructions ? json['route_summary']['start_point'] : nil - end - if table.headers.include? 'end' - got['end'] = instructions ? json['route_summary']['end_point'] : nil - end - if table.headers.include? 'geometry' - got['geometry'] = json['route_geometry'] - end - if table.headers.include? 'route' - got['route'] = (instructions || '').strip - if table.headers.include?('alternative') - got['alternative'] = - if json['found_alternative'] - way_list json['alternative_instructions'].first - else - "" - end - end - if table.headers.include?('distance') - if row['distance']!='' - raise "*** Distance must be specied in meters. (ex: 250m)" unless row['distance'] =~ /\d+m/ - end - got['distance'] = instructions ? "#{json['route_summary']['total_distance'].to_s}m" : '' - end - if table.headers.include?('time') - raise "*** Time must be specied in seconds. (ex: 60s)" unless row['time'] =~ /\d+s/ - got['time'] = instructions ? "#{json['route_summary']['total_time'].to_s}s" : '' - end - if table.headers.include?('speed') - if row['speed'] != '' && instructions - raise "*** Speed must be specied in km/h. (ex: 50 km/h)" unless row['speed'] =~ /\d+ km\/h/ - time = json['route_summary']['total_time'] - distance = json['route_summary']['total_distance'] - speed = time>0 ? (3.6*distance/time).round : nil - got['speed'] = "#{speed} km/h" + if table.headers.include? 'start' + got['start'] = instructions ? json['route_summary']['start_point'] : nil + end + if table.headers.include? 'end' + got['end'] = instructions ? json['route_summary']['end_point'] : nil + end + if table.headers.include? 'geometry' + got['geometry'] = json['route_geometry'] + end + if table.headers.include? 'route' + got['route'] = (instructions || '').strip + if table.headers.include?('alternative') + got['alternative'] = + if json['found_alternative'] + way_list json['alternative_instructions'].first else - got['speed'] = '' + "" end + end + if table.headers.include?('distance') + if row['distance']!='' + raise "*** Distance must be specied in meters. (ex: 250m)" unless row['distance'] =~ /\d+m/ end - if table.headers.include? 'bearing' - got['bearing'] = instructions ? bearings : '' - end - if table.headers.include? 'compass' - got['compass'] = instructions ? compasses : '' - end - if table.headers.include? 'turns' - got['turns'] = instructions ? turns : '' - end - if table.headers.include? 'modes' - got['modes'] = instructions ? modes : '' - end - if table.headers.include? 'times' - got['times'] = instructions ? times : '' - end - if table.headers.include? 'distances' - got['distances'] = instructions ? distances : '' + got['distance'] = instructions ? "#{json['route_summary']['total_distance'].to_s}m" : '' + end + if table.headers.include?('time') + raise "*** Time must be specied in seconds. (ex: 60s)" unless row['time'] =~ /\d+s/ + got['time'] = instructions ? "#{json['route_summary']['total_time'].to_s}s" : '' + end + if table.headers.include?('speed') + if row['speed'] != '' && instructions + raise "*** Speed must be specied in km/h. (ex: 50 km/h)" unless row['speed'] =~ /\d+ km\/h/ + time = json['route_summary']['total_time'] + distance = json['route_summary']['total_distance'] + speed = time>0 ? (3.6*distance/time).round : nil + got['speed'] = "#{speed} km/h" + else + got['speed'] = '' end end + if table.headers.include? 'bearing' + got['bearing'] = instructions ? bearings : '' + end + if table.headers.include? 'compass' + got['compass'] = instructions ? compasses : '' + end + if table.headers.include? 'turns' + got['turns'] = instructions ? turns : '' + end + if table.headers.include? 'modes' + got['modes'] = instructions ? modes : '' + end + if table.headers.include? 'times' + got['times'] = instructions ? times : '' + end + if table.headers.include? 'distances' + got['distances'] = instructions ? distances : '' + end end ok = true diff --git a/features/support/route.rb b/features/support/route.rb index c13dc0e35..935c5be38 100644 --- a/features/support/route.rb +++ b/features/support/route.rb @@ -99,7 +99,7 @@ end def got_route? response if response.code == "200" && !response.body.empty? json = JSON.parse response.body - if json['status'] == 0 + if json['status'] == 200 return way_list( json['route_instructions']).empty? == false end end @@ -109,17 +109,7 @@ end def route_status response if response.code == "200" && !response.body.empty? json = JSON.parse response.body - if json['status'] == 0 - if way_list(json['route_instructions']).empty? - return 'Empty route' - else - return 'x' - end - elsif json['status'] == 207 - '' - else - "Status #{json['status']}" - end + return json['status'] else "HTTP #{response.code}" end diff --git a/features/testbot/status.feature b/features/testbot/status.feature index 43599d8ac..1adb1f76a 100644 --- a/features/testbot/status.feature +++ b/features/testbot/status.feature @@ -14,8 +14,8 @@ Feature: Status messages When I route I should get | from | to | route | status | message | - | a | b | ab | 0 | Found route between points | - | b | a | ab | 0 | Found route between points | + | a | b | ab | 200 | Found route between points | + | b | a | ab | 200 | Found route between points | Scenario: No route found Given the node map @@ -30,8 +30,8 @@ Feature: Status messages When I route I should get | from | to | route | status | message | - | a | b | ab | 0 | Found route between points | - | c | d | cd | 0 | Found route between points | + | a | b | ab | 200 | Found route between points | + | c | d | cd | 200 | Found route between points | | a | c | | 207 | Impossible route between points. | | b | d | | 207 | Impossible route between points. | @@ -46,22 +46,22 @@ Feature: Status messages | ab | When I route I should get - | request | status | message | - | viaroute?loc=1,1&loc=1.01,1 | 0 | Found route between points | - | nonsense | 400 | Bad Request | - | nonsense?loc=1,1&loc=1.01,1 | 400 | Bad Request | - | | 400 | Query string malformed close to position 0 | - | / | 400 | Query string malformed close to position 0 | - | ? | 400 | Query string malformed close to position 0 | - | viaroute/loc= | 400 | Query string malformed close to position 9 | - | viaroute/loc=1 | 400 | Query string malformed close to position 9 | - | viaroute/loc=1,1 | 400 | Query string malformed close to position 9 | - | viaroute/loc=1,1,1 | 400 | Query string malformed close to position 9 | - | viaroute/loc=x | 400 | Query string malformed close to position 9 | - | viaroute/loc=x,y | 400 | Query string malformed close to position 9 | - | viaroute/loc=1,1&loc= | 400 | Query string malformed close to position 9 | - | viaroute/loc=1,1&loc=1 | 400 | Query string malformed close to position 9 | - | viaroute/loc=1,1&loc=1,1 | 400 | Query string malformed close to position 9 | - | viaroute/loc=1,1&loc=1,1,1 | 400 | Query string malformed close to position 9 | - | viaroute/loc=1,1&loc=x | 400 | Query string malformed close to position 9 | - | viaroute/loc=1,1&loc=x,y | 400 | Query string malformed close to position 9 | + | request | status | message | + | viaroute?loc=1,1&loc=1.01,1 | 200 | Found route between points | + | nonsense | 400 | Service not found | + | nonsense?loc=1,1&loc=1.01,1 | 400 | Service not found | + | | 400 | Query string malformed close to position 0 | + | / | 400 | Query string malformed close to position 0 | + | ? | 400 | Query string malformed close to position 0 | + | viaroute?loc= | 400 | Query string malformed close to position 9 | + | viaroute?loc=1 | 400 | Query string malformed close to position 9 | + | viaroute?loc=1,1 | 400 | Invalid coordinates. | + | viaroute?loc=1,1,1 | 400 | Query string malformed close to position 17 | + | viaroute?loc=x | 400 | Query string malformed close to position 9 | + | viaroute?loc=x,y | 400 | Query string malformed close to position 9 | + | viaroute?loc=1,1&loc= | 400 | Query string malformed close to position 17 | + | viaroute?loc=1,1&loc=1 | 400 | Query string malformed close to position 17 | + | viaroute?loc=1,1&loc=1,1 | 200 | Found route between points | + | viaroute?loc=1,1&loc=1,1,1 | 400 | Query string malformed close to position 25 | + | viaroute?loc=1,1&loc=x | 400 | Query string malformed close to position 17 | + | viaroute?loc=1,1&loc=x,y | 400 | Query string malformed close to position 17 | diff --git a/include/osrm/libosrm_config.hpp b/include/osrm/libosrm_config.hpp index d1b8fb5f3..677450a96 100644 --- a/include/osrm/libosrm_config.hpp +++ b/include/osrm/libosrm_config.hpp @@ -36,6 +36,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. struct LibOSRMConfig { std::unordered_map server_paths; + int max_locations_trip = -1; + int max_locations_viaroute = -1; int max_locations_distance_table = -1; int max_locations_map_matching = -1; bool use_shared_memory = true; diff --git a/library/osrm_impl.cpp b/library/osrm_impl.cpp index cfc38e9ed..9031426d9 100644 --- a/library/osrm_impl.cpp +++ b/library/osrm_impl.cpp @@ -85,8 +85,10 @@ OSRM::OSRM_impl::OSRM_impl(LibOSRMConfig& lib_config) RegisterPlugin(new MapMatchingPlugin>( query_data_facade, lib_config.max_locations_map_matching)); RegisterPlugin(new TimestampPlugin>(query_data_facade)); - RegisterPlugin(new ViaRoutePlugin>(query_data_facade)); - RegisterPlugin(new RoundTripPlugin>(query_data_facade)); + RegisterPlugin(new ViaRoutePlugin>(query_data_facade, + lib_config.max_locations_viaroute)); + RegisterPlugin(new RoundTripPlugin>(query_data_facade, + lib_config.max_locations_trip)); } void OSRM::OSRM_impl::RegisterPlugin(BasePlugin *raw_plugin_ptr) @@ -102,13 +104,14 @@ int OSRM::OSRM_impl::RunQuery(const RouteParameters &route_parameters, osrm::jso if (plugin_map.end() == plugin_iterator) { + json_result.values["status_message"] = "Service not found"; return 400; } increase_concurrent_query_count(); - plugin_iterator->second->HandleRequest(route_parameters, json_result); + auto return_code = plugin_iterator->second->HandleRequest(route_parameters, json_result); decrease_concurrent_query_count(); - return 200; + return return_code; } // decrease number of concurrent queries diff --git a/plugins/distance_table.hpp b/plugins/distance_table.hpp index c023a5da1..18c337ac2 100644 --- a/plugins/distance_table.hpp +++ b/plugins/distance_table.hpp @@ -98,11 +98,14 @@ template class DistanceTablePlugin final : public BasePlugin return is_destination; }); - if (number_of_sources * number_of_destination > - max_locations_distance_table * max_locations_distance_table) + if (max_locations_distance_table > 0 && + (number_of_sources * number_of_destination > + max_locations_distance_table * max_locations_distance_table)) { json_result.values["status_message"] = - "Number of bearings does not match number of coordinates."; + "Number of entries " + std::to_string(number_of_sources * number_of_destination) + + " is higher than current maximum (" + + std::to_string(max_locations_distance_table * max_locations_distance_table) + ")"; return 400; } @@ -123,7 +126,8 @@ template class DistanceTablePlugin final : public BasePlugin { if (route_parameters.is_source[i]) { - *phantom_node_source_out_iter = std::make_pair(current_phantom_node, current_phantom_node); + *phantom_node_source_out_iter = + std::make_pair(current_phantom_node, current_phantom_node); if (route_parameters.is_destination[i]) { *phantom_node_target_out_iter = *phantom_node_source_out_iter; @@ -133,8 +137,10 @@ template class DistanceTablePlugin final : public BasePlugin } else { - BOOST_ASSERT(route_parameters.is_destination[i] && !route_parameters.is_source[i]); - *phantom_node_target_out_iter = std::make_pair(current_phantom_node, current_phantom_node); + BOOST_ASSERT(route_parameters.is_destination[i] && + !route_parameters.is_source[i]); + *phantom_node_target_out_iter = + std::make_pair(current_phantom_node, current_phantom_node); phantom_node_target_out_iter++; } continue; @@ -146,11 +152,14 @@ template class DistanceTablePlugin final : public BasePlugin : 180; if (route_parameters.is_source[i]) { - *phantom_node_source_out_iter = facade->NearestPhantomNodeWithAlternativeFromBigComponent(route_parameters.coordinates[i], bearing, range); + *phantom_node_source_out_iter = + facade->NearestPhantomNodeWithAlternativeFromBigComponent( + route_parameters.coordinates[i], bearing, range); // we didn't found a fitting node, return error if (!phantom_node_source_out_iter->first.is_valid(facade->GetNumberOfNodes())) { - json_result.values["status_message"] = std::string("Could not find matching road for via ") + std::to_string(i); + json_result.values["status_message"] = + std::string("Could not find matching road for via ") + std::to_string(i); return 400; } @@ -165,11 +174,14 @@ template class DistanceTablePlugin final : public BasePlugin { BOOST_ASSERT(route_parameters.is_destination[i] && !route_parameters.is_source[i]); - *phantom_node_target_out_iter = facade->NearestPhantomNodeWithAlternativeFromBigComponent(route_parameters.coordinates[i], bearing, range); + *phantom_node_target_out_iter = + facade->NearestPhantomNodeWithAlternativeFromBigComponent( + route_parameters.coordinates[i], bearing, range); // we didn't found a fitting node, return error if (!phantom_node_target_out_iter->first.is_valid(facade->GetNumberOfNodes())) { - json_result.values["status_message"] = std::string("Could not find matching road for via ") + std::to_string(i); + json_result.values["status_message"] = + std::string("Could not find matching road for via ") + std::to_string(i); return 400; } phantom_node_target_out_iter++; @@ -181,11 +193,13 @@ template class DistanceTablePlugin final : public BasePlugin BOOST_ASSERT((phantom_node_target_out_iter - phantom_node_target_vector.begin()) == number_of_destination); - // FIXME we should clear phantom_node_source_vector and phantom_node_target_vector after this + // FIXME we should clear phantom_node_source_vector and phantom_node_target_vector after + // this auto snapped_source_phantoms = snapPhantomNodes(phantom_node_source_vector); auto snapped_target_phantoms = snapPhantomNodes(phantom_node_target_vector); - auto result_table = search_engine_ptr->distance_table(snapped_source_phantoms, snapped_target_phantoms); + auto result_table = + search_engine_ptr->distance_table(snapped_source_phantoms, snapped_target_phantoms); if (!result_table) { diff --git a/plugins/match.hpp b/plugins/match.hpp index 78de2cd49..f31970cb2 100644 --- a/plugins/match.hpp +++ b/plugins/match.hpp @@ -272,10 +272,17 @@ template class MapMatchingPlugin : public BasePlugin int HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) final override { + // enforce maximum number of locations for performance reasons + if (max_locations_map_matching > 0 && + static_cast(route_parameters.coordinates.size()) > max_locations_map_matching) + { + json_result.values["status_message"] = "Too many coodindates."; + return 400; + } + // check number of parameters if (!check_all_coordinates(route_parameters.coordinates)) { - json_result.values["status"] = 400; json_result.values["status_message"] = "Invalid coordinates."; return 400; } @@ -287,31 +294,19 @@ template class MapMatchingPlugin : public BasePlugin const auto &input_bearings = route_parameters.bearings; if (input_timestamps.size() > 0 && input_coords.size() != input_timestamps.size()) { - json_result.values["status"] = 400; json_result.values["status_message"] = "Number of timestamps does not match number of coordinates."; return 400; } if (input_bearings.size() > 0 && input_coords.size() != input_bearings.size()) { - json_result.values["status"] = 400; json_result.values["status_message"] = "Number of bearings does not match number of coordinates."; return 400; } - // enforce maximum number of locations for performance reasons - if (max_locations_map_matching > 0 && - static_cast(input_coords.size()) > max_locations_map_matching) - { - json_result.values["status"] = 400; - json_result.values["status_message"] = "Too many coodindates."; - return 400; - } - // enforce maximum number of locations for performance reasons if (static_cast(input_coords.size()) < 2) { - json_result.values["status"] = 400; json_result.values["status_message"] = "At least two coordinates needed."; return 400; } @@ -320,7 +315,6 @@ template class MapMatchingPlugin : public BasePlugin getCandidates(input_coords, input_bearings, route_parameters.gps_precision, sub_trace_lengths, candidates_lists); if (!found_candidates) { - json_result.values["status"] = 400; json_result.values["status_message"] = "No suitable matching candidates found."; return 400; } @@ -385,15 +379,11 @@ template class MapMatchingPlugin : public BasePlugin if (sub_matchings.empty()) { - json_result.values["status"] = 207; json_result.values["status_message"] = "Cannot find matchings."; - } - else - { - json_result.values["status"] = 0; - json_result.values["status_message"] = "Found matchings."; + return 207; } + json_result.values["status_message"] = "Found matchings."; return 200; } diff --git a/plugins/nearest.hpp b/plugins/nearest.hpp index d92e720b4..58ca7b818 100644 --- a/plugins/nearest.hpp +++ b/plugins/nearest.hpp @@ -62,7 +62,7 @@ template class NearestPlugin final : public BasePlugin const auto &input_bearings = route_parameters.bearings; if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size()) { - json_result.values["status"] = "Number of bearings does not match number of coordinates ."; + json_result.values["status_message"] = "Number of bearings does not match number of coordinates."; return 400; } @@ -73,13 +73,12 @@ template class NearestPlugin final : public BasePlugin if (phantom_node_vector.empty() || !phantom_node_vector.front().phantom_node.is_valid()) { - json_result.values["status"] = 207; + json_result.values["status_message"] = "No nearest edge found."; + return 207; } else { - // reply.status = http::Reply::ok; - json_result.values["status"] = 0; - + json_result.values["status_message"] = "Found nearest edge."; if (number_of_results > 1) { osrm::json::Array results; diff --git a/plugins/trip.hpp b/plugins/trip.hpp index 12ec631bd..ee2a7eb53 100644 --- a/plugins/trip.hpp +++ b/plugins/trip.hpp @@ -63,9 +63,11 @@ template class RoundTripPlugin final : public BasePlugin std::string descriptor_string; DataFacadeT *facade; std::unique_ptr> search_engine_ptr; + int max_locations_trip; public: - explicit RoundTripPlugin(DataFacadeT *facade) : descriptor_string("trip"), facade(facade) + explicit RoundTripPlugin(DataFacadeT *facade, int max_locations_trip) + : descriptor_string("trip"), facade(facade), max_locations_trip(max_locations_trip) { search_engine_ptr = osrm::make_unique>(facade); } @@ -96,8 +98,13 @@ template class RoundTripPlugin final : public BasePlugin } } const int bearing = input_bearings.size() > 0 ? input_bearings[i].first : 0; - const int range = input_bearings.size() > 0 ? (input_bearings[i].second?*input_bearings[i].second:10) : 180; - phantom_node_list.push_back(facade->NearestPhantomNodes(route_parameters.coordinates[i], 1, bearing, range).front().phantom_node); + const int range = input_bearings.size() > 0 + ? (input_bearings[i].second ? *input_bearings[i].second : 10) + : 180; + phantom_node_list.push_back( + facade->NearestPhantomNodes(route_parameters.coordinates[i], 1, bearing, range) + .front() + .phantom_node); BOOST_ASSERT(phantom_node_list.back().is_valid(facade->GetNumberOfNodes())); } @@ -125,8 +132,7 @@ template class RoundTripPlugin final : public BasePlugin BOOST_ASSERT_MSG(component.size() >= range.size(), "scc component and its ranges do not match"); BOOST_ASSERT_MSG(component.size() > 0, "there's no scc component"); - BOOST_ASSERT_MSG(*std::max_element(range.begin(), range.end()) <= - component.size(), + BOOST_ASSERT_MSG(*std::max_element(range.begin(), range.end()) <= component.size(), "scc component ranges are out of bound"); BOOST_ASSERT_MSG(*std::min_element(range.begin(), range.end()) >= 0, "invalid scc component range"); @@ -221,16 +227,17 @@ template class RoundTripPlugin final : public BasePlugin // if from_node is the last node, compute the route from the last to the first location const auto to_node = std::next(it) != end ? *std::next(it) : *start; - viapoint = - PhantomNodes{phantom_node_list[from_node], phantom_node_list[to_node]}; + viapoint = PhantomNodes{phantom_node_list[from_node], phantom_node_list[to_node]}; min_route.segment_end_coordinates.emplace_back(viapoint); } BOOST_ASSERT(min_route.segment_end_coordinates.size() == trip.size()); std::vector uturns(trip.size() + 1); - std::transform(trip.begin(), trip.end(), uturns.begin(), [&route_parameters](const NodeID idx) { - return route_parameters.uturns[idx]; - }); + std::transform(trip.begin(), trip.end(), uturns.begin(), + [&route_parameters](const NodeID idx) + { + return route_parameters.uturns[idx]; + }); uturns.back() = route_parameters.uturns[trip.front()]; search_engine_ptr->shortest_path(min_route.segment_end_coordinates, uturns, min_route); @@ -242,6 +249,15 @@ template class RoundTripPlugin final : public BasePlugin int HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) override final { + if (max_locations_trip > 0 && + (static_cast(route_parameters.coordinates.size()) > max_locations_trip)) + { + json_result.values["status_message"] = + "Number of entries " + std::to_string(route_parameters.coordinates.size()) + + " is higher than current maximum (" + std::to_string(max_locations_trip) + ")"; + return 400; + } + // check if all inputs are coordinates if (!check_all_coordinates(route_parameters.coordinates)) { @@ -250,9 +266,11 @@ template class RoundTripPlugin final : public BasePlugin } const auto &input_bearings = route_parameters.bearings; - if (input_bearings.size() > 0 && route_parameters.coordinates.size() != input_bearings.size()) + if (input_bearings.size() > 0 && + route_parameters.coordinates.size() != input_bearings.size()) { - json_result.values["status_message"] = "Number of bearings does not match number of coordinates."; + json_result.values["status_message"] = + "Number of bearings does not match number of coordinates."; return 400; } @@ -262,7 +280,8 @@ template class RoundTripPlugin final : public BasePlugin // compute the distance table of all phantom nodes const auto result_table = DistTableWrapper( - *search_engine_ptr->distance_table(phantom_node_list, phantom_node_list), number_of_locations); + *search_engine_ptr->distance_table(phantom_node_list, phantom_node_list), + number_of_locations); if (result_table.size() == 0) { @@ -359,6 +378,13 @@ template class RoundTripPlugin final : public BasePlugin json_result.values["trips"] = std::move(trip); + if (trip.values.empty()) + { + json_result.values["status_message"] = "Cannot find trips."; + return 207; + } + + json_result.values["status_message"] = "Found trips."; return 200; } }; diff --git a/plugins/viaroute.hpp b/plugins/viaroute.hpp index b9f8a4436..656b08e4d 100644 --- a/plugins/viaroute.hpp +++ b/plugins/viaroute.hpp @@ -57,9 +57,12 @@ template class ViaRoutePlugin final : public BasePlugin std::string descriptor_string; std::unique_ptr> search_engine_ptr; DataFacadeT *facade; + int max_locations_viaroute; public: - explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade) + explicit ViaRoutePlugin(DataFacadeT *facade, int max_locations_viaroute) + : descriptor_string("viaroute"), facade(facade), + max_locations_viaroute(max_locations_viaroute) { search_engine_ptr = osrm::make_unique>(facade); @@ -75,6 +78,15 @@ template class ViaRoutePlugin final : public BasePlugin int HandleRequest(const RouteParameters &route_parameters, osrm::json::Object &json_result) override final { + if (max_locations_viaroute > 0 && + (static_cast(route_parameters.coordinates.size()) > max_locations_viaroute)) + { + json_result.values["status_message"] = + "Number of entries " + std::to_string(route_parameters.coordinates.size()) + + " is higher than current maximum (" + std::to_string(max_locations_viaroute) + ")"; + return 400; + } + if (!check_all_coordinates(route_parameters.coordinates)) { json_result.values["status_message"] = "Invalid coordinates."; @@ -189,8 +201,9 @@ template class ViaRoutePlugin final : public BasePlugin }); if (not_in_same_component) { + SimpleLogger().Write(logDEBUG) << "Coordinates not in same component."; json_result.values["status_message"] = "Impossible route between points."; - return 400; + return 207; } } diff --git a/routed.cpp b/routed.cpp index 0a5b757cd..90dba245f 100644 --- a/routed.cpp +++ b/routed.cpp @@ -77,7 +77,8 @@ int main(int argc, const char *argv[]) try LibOSRMConfig lib_config; const unsigned init_result = GenerateServerProgramOptions( argc, argv, lib_config.server_paths, ip_address, ip_port, requested_thread_num, - lib_config.use_shared_memory, trial_run, lib_config.max_locations_distance_table, + lib_config.use_shared_memory, trial_run, lib_config.max_locations_viaroute, lib_config.max_locations_trip, + lib_config.max_locations_distance_table, lib_config.max_locations_map_matching); if (init_result == INIT_OK_DO_NOT_START_ENGINE) { diff --git a/server/request_handler.cpp b/server/request_handler.cpp index 52833d0b6..54f039502 100644 --- a/server/request_handler.cpp +++ b/server/request_handler.cpp @@ -52,6 +52,8 @@ RequestHandler::RequestHandler() : routing_machine(nullptr) {} void RequestHandler::handle_request(const http::request ¤t_request, http::reply ¤t_reply) { + osrm::json::Object json_result; + // parse command try { @@ -93,40 +95,40 @@ void RequestHandler::handle_request(const http::request ¤t_request, const bool result = boost::spirit::qi::parse(api_iterator, request_string.end(), api_parser); - osrm::json::Object json_result; // check if the was an error with the request - if (!result || (api_iterator != request_string.end())) + if (result && api_iterator == request_string.end()) + { + // parsing done, lets call the right plugin to handle the request + BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed"); + + if (!route_parameters.jsonp_parameter.empty()) + { // prepend response with jsonp parameter + const std::string json_p = (route_parameters.jsonp_parameter + "("); + current_reply.content.insert(current_reply.content.end(), json_p.begin(), json_p.end()); + } + + const int return_code = routing_machine->RunQuery(route_parameters, json_result); + json_result.values["status"] = return_code; + // 4xx bad request return code + if (return_code / 100 == 4) + { + current_reply.status = http::reply::bad_request; + current_reply.content.clear(); + route_parameters.output_format.clear(); + } + else + { + // 2xx valid request + BOOST_ASSERT(return_code / 100 == 2); + } + } + else { - current_reply = http::reply::stock_reply(http::reply::bad_request); - current_reply.content.clear(); const auto position = std::distance(request_string.begin(), api_iterator); - json_result.values["status"] = 400; - std::string message = "Query string malformed close to position "; - message += std::to_string(position); - json_result.values["status_message"] = message; - osrm::json::render(current_reply.content, json_result); - return; - } - - // parsing done, lets call the right plugin to handle the request - BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed"); - - if (!route_parameters.jsonp_parameter.empty()) - { // prepend response with jsonp parameter - const std::string json_p = (route_parameters.jsonp_parameter + "("); - current_reply.content.insert(current_reply.content.end(), json_p.begin(), json_p.end()); - } - const auto return_code = routing_machine->RunQuery(route_parameters, json_result); - if (200 != return_code) - { - current_reply = http::reply::stock_reply(http::reply::bad_request); - current_reply.content.clear(); - json_result.values["status"] = 400; - std::string message = "Bad Request"; - json_result.values["status_message"] = message; - osrm::json::render(current_reply.content, json_result); - return; + current_reply.status = http::reply::bad_request; + json_result.values["status"] = http::reply::bad_request; + json_result.values["status_message"] = "Query string malformed close to position " + std::to_string(position); } current_reply.headers.emplace_back("Access-Control-Allow-Origin", "*"); @@ -166,10 +168,9 @@ void RequestHandler::handle_request(const http::request ¤t_request, } catch (const std::exception &e) { - current_reply = http::reply::stock_reply(http::reply::internal_server_error); + current_reply = http::reply::stock_reply(http::reply::internal_server_error);; SimpleLogger().Write(logWARNING) << "[server error] code: " << e.what() << ", uri: " << current_request.uri; - return; } } diff --git a/util/routed_options.hpp b/util/routed_options.hpp index 26480f1e7..bfe8e5c36 100644 --- a/util/routed_options.hpp +++ b/util/routed_options.hpp @@ -43,7 +43,8 @@ const static unsigned INIT_OK_START_ENGINE = 0; const static unsigned INIT_OK_DO_NOT_START_ENGINE = 1; const static unsigned INIT_FAILED = -1; -inline void populate_base_path(std::unordered_map &server_paths) +inline void +populate_base_path(std::unordered_map &server_paths) { // populate the server_path object auto path_iterator = server_paths.find("base"); @@ -135,67 +136,69 @@ inline void populate_base_path(std::unordered_map &paths, - std::string &ip_address, - int &ip_port, - int &requested_num_threads, - bool &use_shared_memory, - bool &trial, - int &max_locations_distance_table, - int &max_locations_map_matching) +inline unsigned +GenerateServerProgramOptions(const int argc, + const char *argv[], + std::unordered_map &paths, + std::string &ip_address, + int &ip_port, + int &requested_num_threads, + bool &use_shared_memory, + bool &trial, + int &max_locations_trip, + int &max_locations_viaroute, + int &max_locations_distance_table, + int &max_locations_map_matching) { + using boost::program_options::value; + using boost::filesystem::path; + // declare a group of options that will be allowed only on command line boost::program_options::options_description generic_options("Options"); - generic_options.add_options()("version,v", "Show version")("help,h", "Show this help message")( - "config,c", boost::program_options::value(&paths["config"]) - ->default_value("server.ini"), - "Path to a configuration file")( - "trial", boost::program_options::value(&trial)->implicit_value(true), - "Quit after initialization"); + generic_options.add_options() // + ("version,v", "Show version")("help,h", "Show this help message") // + ("config,c", value(&paths["config"])->default_value("server.ini"), + "Path to a configuration file") // + ("trial", value(&trial)->implicit_value(true), "Quit after initialization"); // declare a group of options that will be allowed both on command line // as well as in a config file boost::program_options::options_description config_options("Configuration"); - config_options.add_options()( - "hsgrdata", boost::program_options::value(&paths["hsgrdata"]), - ".hsgr file")("nodesdata", - boost::program_options::value(&paths["nodesdata"]), - ".nodes file")( - "edgesdata", boost::program_options::value(&paths["edgesdata"]), - ".edges file")("geometry", - boost::program_options::value(&paths["geometries"]), - ".geometry file")( - "ramindex", boost::program_options::value(&paths["ramindex"]), - ".ramIndex file")( - "fileindex", boost::program_options::value(&paths["fileindex"]), - "File index file")( - "namesdata", boost::program_options::value(&paths["namesdata"]), - ".names file")("timestamp", - boost::program_options::value(&paths["timestamp"]), - ".timestamp file")( - "ip,i", boost::program_options::value(&ip_address)->default_value("0.0.0.0"), - "IP address")("port,p", boost::program_options::value(&ip_port)->default_value(5000), - "TCP/IP port")( - "threads,t", boost::program_options::value(&requested_num_threads)->default_value(8), - "Number of threads to use")( - "shared-memory,s", - boost::program_options::value(&use_shared_memory)->implicit_value(true)->default_value(false), - "Load data from shared memory")( - "max-table-size", - boost::program_options::value(&max_locations_distance_table)->default_value(100), - "Max. locations supported in distance table query")( - "max-matching-size", - boost::program_options::value(&max_locations_map_matching)->default_value(100), - "Max. locations supported in map matching query"); + config_options.add_options() // + ("hsgrdata", value(&paths["hsgrdata"]), ".hsgr file") // + ("nodesdata", value(&paths["nodesdata"]), ".nodes file") // + ("edgesdata", value(&paths["edgesdata"]), ".edges file") // + ("geometry", value(&paths["geometries"]), ".geometry file") // + ("ramindex", value(&paths["ramindex"]), ".ramIndex file") // + ("fileindex", value(&paths["fileindex"]), + "File index file") // + ("namesdata", value(&paths["namesdata"]), + ".names file") // + ("timestamp", value(&paths["timestamp"]), + ".timestamp file") // + ("ip,i", value(&ip_address)->default_value("0.0.0.0"), + "IP address") // + ("port,p", value(&ip_port)->default_value(5000), + "TCP/IP port") // + ("threads,t", value(&requested_num_threads)->default_value(8), + "Number of threads to use") // + ("shared-memory,s", + value(&use_shared_memory)->implicit_value(true)->default_value(false), + "Load data from shared memory") // + ("max-viaroute-size", value(&max_locations_viaroute)->default_value(500), + "Max. locations supported in viaroute query") // + ("max-trip-size", value(&max_locations_trip)->default_value(100), + "Max. locations supported in trip query") // + ("max-table-size", value(&max_locations_distance_table)->default_value(100), + "Max. locations supported in distance table query") // + ("max-matching-size", value(&max_locations_map_matching)->default_value(100), + "Max. locations supported in map matching query"); // hidden options, will be allowed both on command line and in config // file, but will not be shown to the user boost::program_options::options_description hidden_options("Hidden options"); - hidden_options.add_options()( - "base,b", boost::program_options::value(&paths["base"]), - "base path to .osrm file"); + hidden_options.add_options()("base,b", value(&paths["base"]), + "base path to .osrm file"); // positional option boost::program_options::positional_options_description positional_options; @@ -274,7 +277,6 @@ inline unsigned GenerateServerProgramOptions(const int argc, SimpleLogger().Write(logWARNING) << "Shared memory settings conflict with path settings."; } - SimpleLogger().Write() << visible_options; return INIT_OK_DO_NOT_START_ENGINE; }