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