Skip to content

Abstract httplib from plugin API, vendor as build farm fallback#347

Draft
bburda wants to merge 9 commits intomainfrom
fix/vendor-cpp-httplib
Draft

Abstract httplib from plugin API, vendor as build farm fallback#347
bburda wants to merge 9 commits intomainfrom
fix/vendor-cpp-httplib

Conversation

@bburda
Copy link
Copy Markdown
Collaborator

@bburda bburda commented Apr 3, 2026

Pull Request

Summary

Removes cpp-httplib from the public plugin API so only ros2_medkit_gateway depends on it. Plugins now use thin PluginRequest/PluginResponse wrappers and declare routes declaratively via get_routes() instead of imperatively registering on httplib::Server.

This also vendors cpp-httplib 0.14.3 in the gateway package with a VENDORED_DIR cmake fallback, fixing the Humble build farm failure where the system package (0.10.x) is too old.


Issue


Type

  • Bug fix
  • New feature or tests
  • Breaking change
  • Documentation only

Testing

  • Full colcon build (13 packages) passes
  • 2422 unit tests pass (0 failures)
  • New unit test RegisterRoutesWrapsPluginHandlers verifies end-to-end route registration and PluginRequest/PluginResponse wrapping
  • New unit tests for PluginRequest (path_param, header, path, body) and PluginResponse (send_json, send_error)
  • Integration test updated for demo plugin response format change (plaintext -> JSON)
  • Linters pass

Checklist

  • Breaking changes are clearly described (and announced in docs / changelog if needed)
  • Tests were added or updated if needed
  • Docs were updated if behavior or public API changed

Breaking changes

  • PLUGIN_API_VERSION bumped 4 -> 5
  • GatewayPlugin::register_routes() and get_route_descriptions() removed, replaced by get_routes() returning vector<PluginRoute>
  • PluginContext::send_json() and send_error() static methods removed, now instance methods on PluginResponse
  • Plugin route handlers receive PluginRequest/PluginResponse instead of httplib::Request/httplib::Response
  • Plugin packages no longer need libcpp-httplib-dev, libssl-dev, or medkit_find_cpp_httplib() in CMake

bburda added 8 commits April 2, 2026 19:52
Add httplib.h v0.14.3 (MIT) to gateway vendored directory.
Update medkit_find_cpp_httplib() macro to accept VENDORED_DIR parameter
as fallback when system package is too old (Ubuntu 22.04 ships 0.10.x).

Fixes #341
Thin wrappers over httplib::Request/Response that hide the HTTP library
from plugin code. Implementation compiled in gateway_lib; plugins
resolve symbols at runtime from the gateway process.
Plugins now declare routes via get_routes() returning PluginRoute structs
instead of imperatively registering on httplib::Server. The gateway wraps
httplib types in PluginRequest/PluginResponse before calling handlers.

Removes httplib from the public plugin API. PLUGIN_API_VERSION bumped 4->5.
Replace register_routes(httplib::Server&, prefix) with get_routes() returning
vector<PluginRoute>. Handler now uses PluginRequest/PluginResponse instead of
httplib types directly. Remove httplib and OpenSSL build/package dependencies
from plugin target; keep only for test target which does end-to-end HTTP testing.
Update FakePluginContext::validate_entity_for_route and add PluginRequest/
PluginResponse stubs in the test.
Replace register_routes + get_route_descriptions with get_routes() returning
vector<PluginRoute>. Handler now uses PluginRequest/PluginResponse instead of
httplib types directly. Remove httplib and OpenSSL build/package dependencies.
Update MockPluginContext::validate_entity_for_route and stubs in test.
Replace register_routes + get_route_descriptions with get_routes() returning
vector<PluginRoute>. Handler now uses PluginRequest/PluginResponse instead of
httplib types directly. Remove httplib and OpenSSL build/package dependencies.
Update MockPluginContext::validate_entity_for_route and stubs in test.
Replace register_routes(httplib::Server&, prefix) with get_routes() returning
vector<PluginRoute> in procfs, systemd, and container plugins. Handlers now use
PluginRequest/PluginResponse instead of httplib types directly. Remove httplib
and OpenSSL build/package dependencies from all three plugin targets and tests.
Copilot AI review requested due to automatic review settings April 3, 2026 09:26
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the gateway plugin HTTP surface to remove cpp-httplib from the public plugin API by introducing PluginRequest/PluginResponse wrappers and a declarative GatewayPlugin::get_routes() route model, and adds a vendored cpp-httplib fallback to address Humble/Jammy build farm constraints.

Changes:

  • Replace plugin route registration (register_routes) with get_routes() returning PluginRoute handlers using PluginRequest/PluginResponse.
  • Vendor cpp-httplib (intended 0.14.3) and extend medkit_find_cpp_httplib() with a VENDORED_DIR fallback tier.
  • Update affected plugins, unit tests, integration tests, and documentation to the v5 plugin API.

Reviewed changes

Copilot reviewed 42 out of 42 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
src/ros2_medkit_gateway/include/ros2_medkit_gateway/plugins/gateway_plugin.hpp Introduces PluginRoute + get_routes() API.
src/ros2_medkit_gateway/include/ros2_medkit_gateway/plugins/plugin_http_types.hpp Adds PluginRequest/PluginResponse wrapper types.
src/ros2_medkit_gateway/src/plugins/plugin_http_types.cpp Implements wrappers via HandlerContext::send_json/send_error.
src/ros2_medkit_gateway/src/plugins/plugin_manager.cpp Wraps/installs plugin routes onto the HTTP server via get_routes().
src/ros2_medkit_gateway/include/ros2_medkit_gateway/plugins/plugin_manager.hpp Hides httplib from the header by using an opaque server pointer.
src/ros2_medkit_gateway/src/http/rest_server.cpp Adapts route registration callsite to new register_routes(void*) signature.
src/ros2_medkit_gateway/src/plugins/plugin_context.cpp / include/.../plugin_context.hpp Switches validate_entity_for_route to PluginRequest/PluginResponse and removes static response helpers.
src/ros2_medkit_gateway/include/ros2_medkit_gateway/plugins/plugin_types.hpp Bumps PLUGIN_API_VERSION to 5.
src/ros2_medkit_gateway/CMakeLists.txt Uses medkit_find_cpp_httplib(VENDORED_DIR ...), adds wrapper source, installs vendored header.
src/ros2_medkit_cmake/cmake/ROS2MedkitCompat.cmake Adds VENDORED_DIR fallback support to medkit_find_cpp_httplib().
src/ros2_medkit_cmake/README.md Documents the new vendored fallback parameter.
src/ros2_medkit_gateway/src/vendored/cpp_httplib/LICENSE Adds vendored dependency license.
src/ros2_medkit_gateway/src/vendored/cpp_httplib/httplib.h Adds vendored cpp-httplib header (intended fallback).
src/ros2_medkit_gateway/test/test_plugin_manager.cpp Updates tests for get_routes() and adds an end-to-end wrapping test.
src/ros2_medkit_gateway/test/test_plugin_http_types.cpp Adds unit tests for PluginRequest/PluginResponse.
src/ros2_medkit_gateway/test/demo_nodes/test_gateway_plugin.cpp Updates demo plugin to new route/response API (JSON ping).
src/ros2_medkit_integration_tests/test/features/test_plugin_vendor_extensions.test.py Updates integration assertion to expect JSON response.
src/ros2_medkit_plugins/ros2_medkit_graph_provider/src/graph_provider_plugin.cpp Migrates to get_routes() + wrappers.
src/ros2_medkit_plugins/ros2_medkit_graph_provider/include/.../graph_provider_plugin.hpp Updates plugin interface override to get_routes().
src/ros2_medkit_plugins/ros2_medkit_graph_provider/test/test_graph_provider_plugin.cpp Updates route tests and provides wrapper stubs for non-gateway-linked tests.
src/ros2_medkit_plugins/ros2_medkit_graph_provider/CMakeLists.txt / package.xml Removes httplib/openssl deps from plugin; re-adds for route tests only.
src/ros2_medkit_discovery_plugins/ros2_medkit_topic_beacon/src/topic_beacon_plugin.cpp Migrates to get_routes() + wrappers.
src/ros2_medkit_discovery_plugins/ros2_medkit_topic_beacon/test/test_topic_beacon_plugin.cpp Updates stubs and context signature for new HTTP types.
src/ros2_medkit_discovery_plugins/ros2_medkit_topic_beacon/CMakeLists.txt / package.xml / include/...hpp Removes httplib/openssl deps and old route APIs.
src/ros2_medkit_discovery_plugins/ros2_medkit_param_beacon/src/param_beacon_plugin.cpp Migrates to get_routes() + wrappers.
src/ros2_medkit_discovery_plugins/ros2_medkit_param_beacon/test/test_param_beacon_plugin.cpp Updates stubs and context signature for new HTTP types.
src/ros2_medkit_discovery_plugins/ros2_medkit_param_beacon/CMakeLists.txt / package.xml / include/...hpp Removes httplib/openssl deps and old route APIs.
src/ros2_medkit_discovery_plugins/ros2_medkit_linux_introspection/src/{procfs,systemd,container}_plugin.cpp Migrates to get_routes() + wrappers and response helpers on PluginResponse.
src/ros2_medkit_discovery_plugins/ros2_medkit_linux_introspection/CMakeLists.txt / package.xml / design/index.rst Removes httplib/openssl deps and updates design docs for new API.
docs/tutorials/plugin-system.rst Updates tutorial to API v5 + new route/response model.
docs/config/server.rst Updates plugin lifecycle docs to get_routes().
docs/troubleshooting.rst Updates troubleshooting reference to get_routes().
Comments suppressed due to low confidence (1)

src/ros2_medkit_gateway/CMakeLists.txt:62

  • With the new VENDORED_DIR fallback, gateway_lib may compile against the vendored cpp-httplib while test targets still include <httplib.h> from the system (e.g., 0.10.x on Humble). That can lead to ABI/type mismatches (tests constructing httplib::Request/Server with one header version while gateway_lib is built against another) and even missing APIs like wait_until_ready(). Consider forcing all targets in this package (especially gtests) to build against the same cpp_httplib_target include directory (e.g., by linking cpp_httplib_target PUBLIC from gateway_lib or adding it explicitly to each test target) so the vendored fallback is exercised safely on the build farm.
medkit_find_cpp_httplib(VENDORED_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src/vendored/cpp_httplib")

# Find OpenSSL (required by jwt-cpp for RS256 and optional TLS support)
find_package(OpenSSL REQUIRED)

# Enable OpenSSL support for cpp-httplib SSLServer
# This enables the httplib::SSLServer class for HTTPS support
add_compile_definitions(CPPHTTPLIB_OPENSSL_SUPPORT)

Comment on lines +839 to +847
Server();

virtual ~Server();

virtual bool is_valid() const;

Server &Get(const std::string &pattern, Handler handler);
Server &Post(const std::string &pattern, Handler handler);
Server &Post(const std::string &pattern, HandlerWithContentReader handler);
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

The vendored httplib.h appears to contain only declarations for core APIs (e.g., httplib::Server::Get/Post/..., listen, bind_to_any_port, etc.) but the file ends without providing their definitions (no Server::Get(...) implementation is present). Since cpp-httplib is expected to be header-only in the vendored fallback, this will cause link errors (or require a separate compiled library that is not provided). Please vendor the complete upstream single-header for 0.14.3 (or add the corresponding .cc and build/link it) so the VENDORED_DIR fallback is actually usable on the Humble build farm.

Copilot uses AI. Check for mistakes.
Comment on lines +346 to +353
std::thread server_thread([&srv]() {
srv.listen("127.0.0.1", 18321);
});
srv.wait_until_ready();

// Make request to the plugin route
httplib::Client cli("127.0.0.1", 18321);
auto res = cli.Get("/api/v1/apps/test_entity/x-test-route");
Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

This test starts an HTTP server on a fixed port (18321). That can flake under parallel CTest runs or if the port is already in use. Prefer binding to an ephemeral port (bind_to_any_port("127.0.0.1") + listen_after_bind()) like other gateway tests, and use the returned port for the client.

Copilot uses AI. Check for mistakes.
Comment on lines +86 to +90
# The route test uses httplib::Server/Client directly for end-to-end HTTP testing.
# Find cpp-httplib so the test binary can link against the compiled implementation.
find_package(OpenSSL REQUIRED)
medkit_find_cpp_httplib()

Copy link

Copilot AI Apr 3, 2026

Choose a reason for hiding this comment

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

medkit_find_cpp_httplib() is still invoked under BUILD_TESTING without a VENDORED_DIR fallback. On Humble/Jammy (the build farm case in #341), the only available system package is 0.10.x, so this will still fail configuration whenever tests are enabled. Consider reusing the gateway's vendored header for these tests (e.g., include it via the ros2_medkit_gateway exported vendored include dir / explicit include path) or pass an appropriate VENDORED_DIR so test builds don't regress on Humble.

Copilot uses AI. Check for mistakes.
@bburda bburda self-assigned this Apr 3, 2026
@bburda bburda requested a review from mfaferek93 April 3, 2026 10:03
@bburda bburda marked this pull request as draft April 3, 2026 10:14
- Fix missing '/' between api_prefix and route pattern in
  PluginManager::register_routes (produced /api/v1apps/... instead
  of /api/v1/apps/...)
- Fix integration test expecting plaintext 'pong' after demo plugin
  was changed to return JSON
- Update plugin-system.rst, server.rst, troubleshooting.rst, and
  linux_introspection design doc to reference new get_routes() API
  instead of removed register_routes()
- Update documented API version from 4 to 5
- Remove dead code get_all_route_info() (zero callers)
- Add unit test verifying PluginManager route wrapping end-to-end
@bburda bburda force-pushed the fix/vendor-cpp-httplib branch from 40a5256 to 89acca5 Compare April 3, 2026 11:28
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.

[BUG] Humble build farm fails: cpp-httplib 0.10.x too old

2 participants