LCOV - code coverage report
Current view: top level - http/server/routing - route.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 100.0 % 4 4
Test Date: 2026-04-21 17:49:55 Functions: 100.0 % 4 4

            Line data    Source code
       1              : #ifndef THINGER_HTTP_ROUTE_DESCRIPTOR_HPP
       2              : #define THINGER_HTTP_ROUTE_DESCRIPTOR_HPP
       3              : 
       4              : #include <functional>
       5              : #include <regex>
       6              : #include <string>
       7              : #include <vector>
       8              : #include <memory>
       9              : #include "../request.hpp"
      10              : #include "../../../util/types.hpp"
      11              : 
      12              : #ifdef THINGER_HTTP_VALIJSON_ENABLED
      13              : #include <valijson/schema.hpp>
      14              : #include <valijson/schema_parser.hpp>
      15              : #include <valijson/validator.hpp>
      16              : #include <valijson/validation_results.hpp>
      17              : #include <valijson/adapters/nlohmann_json_adapter.hpp>
      18              : #endif
      19              : 
      20              : namespace thinger::http {
      21              : 
      22              : // Route parameters syntax:
      23              : // 1. Simple parameters: :param_name
      24              : //    Example: "/api/v1/users/:user/devices/:device"
      25              : //    Matches any non-slash characters
      26              : //
      27              : // 2. Parameters with custom regex: :param_name(regex)
      28              : //    Example: "/api/v1/users/:id([0-9]+)"         - numeric ID only
      29              : //    Example: "/api/v1/users/:user([a-zA-Z0-9_-]{1,32})" - alphanumeric with length limit
      30              : //    Example: "/files/:path(.+)"                   - match everything including slashes
      31              : //
      32              : // Common patterns:
      33              : #define ID_PATTERN      "[0-9]+"                      // Numeric ID
      34              : #define ALPHANUM_ID     "[a-zA-Z0-9_-]{1,32}"        // Alphanumeric ID (1-32 chars)
      35              : #define UUID_PATTERN    "[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}"
      36              : #define EMAIL_PATTERN   "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}"
      37              : #define SLUG_PATTERN    "[a-z0-9]+(?:-[a-z0-9]+)*"   // URL-friendly slug
      38              : 
      39              : // Authorization levels
      40              : enum class auth_level {
      41              :     PUBLIC,     // No authentication required
      42              :     USER,       // Valid user required
      43              :     ADMIN       // Admin user required
      44              : };
      45              : 
      46              : // Forward declarations
      47              : class request;
      48              : class response;
      49              : 
      50              : // Callback types for route handlers - supporting multiple signatures
      51              : using route_callback_response_only = std::function<void(response&)>;
      52              : using route_callback_json_response = std::function<void(nlohmann::json&, response&)>;
      53              : using route_callback_request_response = std::function<void(request&, response&)>;
      54              : using route_callback_request_json_response = std::function<void(request&, nlohmann::json&, response&)>;
      55              : using route_callback_awaitable = std::function<thinger::awaitable<void>(request&, response&)>;
      56              : 
      57              : // Legacy callback types (for backward compatibility if needed)
      58              : using route_callback = route_callback_request_response;
      59              : using route_callback_json = route_callback_request_json_response;
      60              : 
      61              : class route {
      62              : public:
      63              :     route(const std::string& pattern);
      64              :     
      65              :     // Set the callback handler - multiple signatures supported
      66              :     route& operator=(route_callback_response_only callback);
      67              :     route& operator=(route_callback_json_response callback);
      68              :     route& operator=(route_callback_request_response callback);
      69              :     route& operator=(route_callback_request_json_response callback);
      70              :     route& operator=(route_callback_awaitable callback);
      71              :     
      72              :     // Deferred body mode - handler reads body at its discretion
      73              :     route& deferred_body(bool enabled = true);
      74         1023 :     bool is_deferred_body() const { return deferred_body_; }
      75              : 
      76              :     // Set JSON Schema for request body validation
      77              :     route& schema(const nlohmann::json& json_schema);
      78              : 
      79              :     // Set authorization level
      80              :     route& auth(auth_level level);
      81              : 
      82              :     // Set description for API documentation
      83              :     route& description(const std::string& desc);
      84              :     
      85              :     // Check if route matches the given path
      86              :     bool matches(const std::string& path, std::smatch& matches) const;
      87              :     
      88              :     // Get route parameters from regex
      89         1585 :     const std::vector<std::string>& get_parameters() const { return parameters_; }
      90              :     
      91              :     // Get authorization level
      92         1031 :     auth_level get_auth_level() const { return auth_level_; }
      93              :     
      94              :     // Handle the request (synchronous)
      95              :     void handle_request(request& req, response& res) const;
      96              : 
      97              :     // Handle the request (coroutine — works for all callback types)
      98              :     thinger::awaitable<void> handle_request_coro(request& req, response& res) const;
      99              :     
     100              :     // Get the original pattern
     101         1028 :     const std::string& get_pattern() const { return pattern_; }
     102              :     
     103              : private:
     104              :     std::string pattern_;
     105              :     std::regex regex_;
     106              :     std::vector<std::string> parameters_;
     107              :     auth_level auth_level_ = auth_level::PUBLIC;
     108              :     std::string description_;
     109              :     bool deferred_body_ = false;
     110              :     std::variant<
     111              :         route_callback_response_only,
     112              :         route_callback_json_response,
     113              :         route_callback_request_response,
     114              :         route_callback_request_json_response,
     115              :         route_callback_awaitable
     116              :     > callback_;
     117              : 
     118              : #ifdef THINGER_HTTP_VALIJSON_ENABLED
     119              :     nlohmann::json json_schema_;
     120              :     std::shared_ptr<valijson::Schema> schema_;
     121              : 
     122              :     bool validate_json(const nlohmann::json& json, response& res) const;
     123              : #endif
     124              : 
     125              :     void parse_parameters();
     126              : };
     127              : 
     128              : } // namespace thinger::http
     129              : 
     130              : #endif // THINGER_HTTP_ROUTE_DESCRIPTOR_HPP
        

Generated by: LCOV version 2.0-1