Skip to content

feat(http): add POST request support - #7676

Open
DennisOSRM wants to merge 2 commits into
masterfrom
dlx/post
Open

feat(http): add POST request support#7676
DennisOSRM wants to merge 2 commits into
masterfrom
dlx/post

Conversation

@DennisOSRM

@DennisOSRM DennisOSRM commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

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:

  • include/server/api/json_parameters_parser.hpp -- header for the JSON parameter parser
  • src/server/api/json_parameters_parser.cpp -- implementation, ~570 lines
  • unit_tests/server/json_parameters_parser.cpp -- unit tests

Key changes in existing files:

  • src/server/request_handler.cpp -- dispatches to the JSON parser for POST, URL parser for GET
  • src/server/service/route_service.cpp and table_service.cpp -- accept either parameter type
  • src/server/connection.cpp -- reads the POST body up to a configurable maximum size
  • include/server/header_size.hpp -- bumped the maximum header/body size
  • src/tools/routed.cpp -- wired up the new parser
  • docs/http.md -- documented the JSON request format
  • features/support/http.js and route.js -- updated Cucumber test helpers

Cleanup along the way:

  • Removed two unused headers (postprocessing_toolkit.hpp, name_table.hpp)
  • Added missing #include guards in a few engine headers

implements #7660

Copilot AI lite review requested due to automatic review settings August 5, 2026 17:19

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 route and table, 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.

Comment on lines +49 to +53
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;
}

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Replaced ::tolower with a lambda that casts to unsigned char first.

Comment thread include/server/request_handler.hpp
Comment thread src/server/request_handler.cpp
Comment thread src/server/request_handler.cpp Outdated
Comment on lines +185 to +189
// 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());

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed. Both log lines now check LogPolicy::GetInstance().IsMute() before calling CompactJsonForLog.

Comment on lines +57 to +63
// 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

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. Added #include <cstddef>.

@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 79.46903% with 116 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.97%. Comparing base (ccf2a8e) to head (7b5238a).
⚠️ Report is 2 commits behind head on master.

Files with missing lines Patch % Lines
src/server/api/json_parameters_parser.cpp 75.42% 73 Missing ⚠️
src/server/request_handler.cpp 74.35% 20 Missing ⚠️
include/server/service/base_service.hpp 0.00% 7 Missing ⚠️
src/server/service/table_service.cpp 68.42% 6 Missing ⚠️
src/server/service/route_service.cpp 84.21% 3 Missing ⚠️
src/server/api/url_parser.cpp 88.23% 2 Missing ⚠️
src/server/service_handler.cpp 85.71% 2 Missing ⚠️
include/engine/hint.hpp 0.00% 1 Missing ⚠️
include/server/header_size.hpp 90.00% 1 Missing ⚠️
include/server/request_handler.hpp 80.00% 1 Missing ⚠️
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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HTTP POST support

2 participants