Abstract httplib from plugin API, vendor as build farm fallback#347
Abstract httplib from plugin API, vendor as build farm fallback#347
Conversation
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.
There was a problem hiding this comment.
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) withget_routes()returningPluginRoutehandlers usingPluginRequest/PluginResponse. - Vendor
cpp-httplib(intended 0.14.3) and extendmedkit_find_cpp_httplib()with aVENDORED_DIRfallback 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_DIRfallback,gateway_libmay 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 constructinghttplib::Request/Serverwith one header version whilegateway_libis built against another) and even missing APIs likewait_until_ready(). Consider forcing all targets in this package (especially gtests) to build against the samecpp_httplib_targetinclude directory (e.g., by linkingcpp_httplib_targetPUBLIC fromgateway_libor 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)
| 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); |
There was a problem hiding this comment.
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.
| 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"); |
There was a problem hiding this comment.
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.
| # 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() | ||
|
|
There was a problem hiding this comment.
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.
- 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
40a5256 to
89acca5
Compare
Pull Request
Summary
Removes cpp-httplib from the public plugin API so only
ros2_medkit_gatewaydepends on it. Plugins now use thinPluginRequest/PluginResponsewrappers and declare routes declaratively viaget_routes()instead of imperatively registering onhttplib::Server.This also vendors cpp-httplib 0.14.3 in the gateway package with a
VENDORED_DIRcmake fallback, fixing the Humble build farm failure where the system package (0.10.x) is too old.Issue
Type
Testing
RegisterRoutesWrapsPluginHandlersverifies end-to-end route registration and PluginRequest/PluginResponse wrappingPluginRequest(path_param, header, path, body) andPluginResponse(send_json, send_error)Checklist
Breaking changes
PLUGIN_API_VERSIONbumped 4 -> 5GatewayPlugin::register_routes()andget_route_descriptions()removed, replaced byget_routes()returningvector<PluginRoute>PluginContext::send_json()andsend_error()static methods removed, now instance methods onPluginResponsePluginRequest/PluginResponseinstead ofhttplib::Request/httplib::Responselibcpp-httplib-dev,libssl-dev, ormedkit_find_cpp_httplib()in CMake