LCOV - code coverage report
Current view: top level - http/server/routing - route_handler.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 13 13
Test Date: 2026-11-10 10:38:07 Functions: 97.5 % 40 39

            Line data    Source code
       1              : #ifndef THINGER_HTTP_ROUTE_HANDLER_HPP
       2              : #define THINGER_HTTP_ROUTE_HANDLER_HPP
       3              : 
       4              : #include <deque>
       5              : #include <map>
       6              : #include <memory>
       7              : #include "route.hpp"
       8              : #include "route_builder.hpp"
       9              : #include "route_tree.hpp"
      10              : 
      11              : namespace thinger::http {
      12              : 
      13              : class route_handler {
      14              : public:
      15              :     // Fallback for unmatched requests
      16              :     using fallback_handler = route_callback_awaitable;
      17              : 
      18              :     route_handler();
      19        11913 :     virtual ~route_handler() = default;
      20              :     
      21              :     // Access route builders for different HTTP methods
      22              :     route_builder operator[](method http_method);
      23              : 
      24              :     // Find the matching route for a request (without executing the handler), setting it
      25              :     // and its path parameters on the request. Routes are matched by path segments, by
      26              :     // priority: static segments, then segments with a regex constraint, then parameters,
      27              :     // then parameters that may match '/' (see route_tree), whatever their registration order.
      28              :     // A HEAD request matching no HEAD route is matched with the GET routes (the response
      29              :     // drops the body), so an explicit HEAD route wins.
      30              :     const route* find_route(std::shared_ptr<request> req);
      31              : 
      32              :     // Handle an unmatched request through the response: the fallback handler, else 404 for
      33              :     // a method with routes (HEAD has those of GET), or 405 for a method without any, with the
      34              :     // methods of the routes matching the path in its Allow header (HEAD wherever GET)
      35              :     thinger::awaitable<void> handle_unmatched(request& req, response& res);
      36              : 
      37              :     // Add a catch-all handler for unmatched routes, taking (request&, response&) or
      38              :     // (response&), synchronous or coroutine. An empty one (nullptr, or an empty
      39              :     // std::function) removes it: unmatched requests are answered 404/405 again.
      40              :     template<request_handler_callable F>
      41          848 :     void set_fallback_handler(F&& handler) {
      42          848 :         fallback_handler_ = make_route_callback(std::forward<F>(handler));
      43          848 :     }
      44            3 :     void set_fallback_handler(std::nullptr_t) { fallback_handler_ = nullptr; }
      45              :     
      46              :     // Get all registered routes (useful for API documentation). Routes are never moved
      47              :     // once registered: references to them stay valid while more routes are added.
      48           80 :     const std::map<method, std::deque<route>>& get_routes() const { return routes_; }
      49              : 
      50              :     // Shared JSON schemas (OpenAPI components), referenced from route schemas with
      51              :     // {"$ref": "#/components/schemas/<name>"}. Register them before the routes using them.
      52           19 :     void add_schema_component(const std::string& name, nlohmann::json schema) {
      53           19 :         schema_components_[name] = std::move(schema);
      54           19 :     }
      55           53 :     const nlohmann::json& get_schema_components() const { return schema_components_; }
      56              :     
      57              : private:
      58              :     std::map<method, std::deque<route>> routes_;
      59              :     // The same routes, by method, as trees of path segments for matching
      60              :     std::map<method, route_tree> trees_;
      61              :     nlohmann::json schema_components_ = nlohmann::json::object();
      62              :     fallback_handler fallback_handler_;
      63              : 
      64              :     // Route of a method matching a path, appending its parameters to `captures`; null if none
      65        90902 :     const route_tree::leaf* match(method http_method, std::string_view path,
      66              :                                   detail::route_captures& captures) const {
      67        90902 :         auto tree = trees_.find(http_method);
      68        90902 :         return tree != trees_.end() ? tree->second.find(path, captures) : nullptr;
      69              :     }
      70              :     
      71              :     // Friend class to allow route_builder to access routes_
      72              :     friend class route_builder;
      73              : };
      74              : 
      75              : } // namespace thinger::http
      76              : 
      77              : #endif // THINGER_HTTP_ROUTE_HANDLER_HPP
        

Generated by: LCOV version 2.0-1