feat(http): add POST request support - #7676
Conversation
There was a problem hiding this comment.
Pull request overview
Adds HTTP POST support (JSON request bodies) for OSRM’s HTTP API, implementing the request discussed in #7660. This extends the existing Boost.Beast server so route and table can accept coordinates/options in the body to avoid URL/header size limits, while keeping GET behavior intact.
Changes:
- Added a JSON-body parameter parser and POST execution path for
routeandtable, including request-body size limiting. - Updated request handling for method routing (GET/HEAD/POST/OPTIONS), CORS headers, and logging.
- Added unit + cucumber coverage to validate JSON parsing and GET/POST equivalence, plus updated HTTP docs.
Reviewed changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| unit_tests/server/json_parameters_parser.cpp | New unit tests for JSON parameter parsing and parity with URL parsing. |
| src/tools/routed.cpp | Adds --max-request-body-size and plumbs body size into server creation/logging. |
| src/server/service/table_service.cpp | Adds RunJSONQuery for table and shares GET/POST execution via runTable. |
| src/server/service/route_service.cpp | Adds RunJSONQuery for route and shares GET/POST execution via runRoute. |
| src/server/service_handler.cpp | Refactors service resolution and adds JSON-body query dispatch. |
| src/server/request_handler.cpp | Implements method handling (OPTIONS/POST), content-type checks, and POST routing. |
| src/server/connection.cpp | Sets Beast parser body_limit() based on configured max request body size. |
| src/server/api/url_parser.cpp | Adds parseURLPrefix for POST endpoints without query-in-URL. |
| src/server/api/json_parameters_parser.cpp | New JSON-to-parameters parser for Route/Table (RapidJSON-based). |
| include/server/service/table_service.hpp | Declares RunJSONQuery override for table. |
| include/server/service/route_service.hpp | Declares RunJSONQuery override for route. |
| include/server/service/base_service.hpp | Adds default RunJSONQuery returning NotImplemented. |
| include/server/service_handler.hpp | Extends handler interface with POST/JSON overload. |
| include/server/server.hpp | Plumbs max_body_size through Server::CreateServer and constructor. |
| include/server/request_handler.hpp | Adds shared CORS header helper used by responses/errors. |
| include/server/header_size.hpp | Adds deriveMaxBodySize() to size POST body limits from config. |
| include/server/connection.hpp | Stores and passes max_body_size_ to the HTTP parser. |
| include/server/api/url_parser.hpp | Declares parseURLPrefix helpers. |
| include/server/api/json_parameters_parser.hpp | New public interface for JSON parameter parsing. |
| include/extractor/name_table.hpp | Removes deprecated forwarding header. |
| include/engine/hint.hpp | Adds defaulted equality for Hint to enable value comparisons in tests. |
| include/engine/guidance/postprocessing_toolkit.hpp | Removes deprecated/unused header. |
| include/engine/api/table_parameters.hpp | Adds defaulted equality for TableParameters. |
| include/engine/api/route_parameters.hpp | Adds defaulted equality for RouteParameters. |
| include/engine/api/base_parameters.hpp | Adds defaulted equality for BaseParameters. |
| features/support/route.js | Adds GET/POST equivalence checks for route/table in cucumber tests. |
| features/support/http.js | Adds a POST-capable HTTP helper for cucumber tests. |
| docs/http.md | Documents POST JSON body API for route/table and body-size option. |
Suppressed comments (1)
src/server/request_handler.cpp:270
- The access log line also unconditionally evaluates
is_post ? " " + CompactJsonForLog(current_request.body()) : ...even when logging is muted, because the concatenation happens before util::Log() can short-circuit. Wrapping the access-log emission with a LogPolicy check avoids parsing/compacting potentially large bodies when nothing will be logged.
<< request_string
// POST: append the JSON body (compacted to one line) so the request
// can be replayed from the log alone.
<< (is_post ? " " + CompactJsonForLog(current_request.body())
: std::string());
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| bool IsJsonContentType(std::string content_type) | ||
| { | ||
| std::transform(content_type.begin(), content_type.end(), content_type.begin(), ::tolower); | ||
| return content_type.rfind("application/json", 0) == 0; | ||
| } |
There was a problem hiding this comment.
Fixed. Replaced ::tolower with a lambda that casts to unsigned char first.
| // Echo every incoming request to the console as a single line. GET carries its full query | ||
| // in the URL; POST additionally gets its JSON body appended (compacted to one line) so both | ||
| // request types are logged identically and can be replayed from the log alone. | ||
| util::Log() << "[req][" << tid << "] " << request_string | ||
| << (is_post ? " " + CompactJsonForLog(current_request.body()) : std::string()); |
There was a problem hiding this comment.
Fixed. Both log lines now check LogPolicy::GetInstance().IsMute() before calling CompactJsonForLog.
| // Estimates the maximum HTTP request body size (for POST requests with a JSON body). | ||
| // A JSON coordinate such as `[13.388000,52.517000],` is ~24 bytes; per-coordinate options | ||
| // (hints, bearings, ...) add more, so we budget generously per coordinate on top of a | ||
| // fixed floor to accommodate the surrounding JSON structure and options. | ||
| inline std::size_t deriveMaxBodySize(const engine::EngineConfig &config) | ||
| { | ||
| constexpr std::size_t MIN_BODY_SIZE = 1024 * 1024; // 1 MiB |
There was a problem hiding this comment.
Good catch. Added #include <cstddef>.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## master #7676 +/- ##
==========================================
+ Coverage 93.83% 93.97% +0.14%
==========================================
Files 484 487 +3
Lines 41371 38351 -3020
==========================================
- Hits 38820 36041 -2779
+ Misses 2551 2310 -241 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
This PR adds HTTP POST support to the OSRM server (fixes #7660). Previously, clients had to encode all parameters into long GET URL query strings. This was awkward for complex requests with many coordinates, options, or hints, and it meant OSRM was the only major routing engine without POST support.
What changed:
The server now accepts JSON-encoded parameters in the POST body for the /route and /table endpoints. The existing URL-based GET flow is untouched; both methods work side by side.
A new json_parameters_parser reads JSON bodies and validates them against the same parameter schemas used by the URL parser. Both the route and table services were extended to accept either parameter source. The connection handler detects the HTTP method and routes accordingly.
New files:
Key changes in existing files:
Cleanup along the way:
implements #7660