1#define _POSIX_C_SOURCE 200809L
16#define CWIST_MUX_DEFAULT_BUCKETS 4099
31 uint64_t hi = 14695981039346656037ULL;
39 for (
size_t i = 0;
i <
sizeof(method); ++
i) {
84 return (cwist_mux_signature){.hi = hi, .lo = lo};
94 const cwist_mux_signature *
sig) {
99 hash *= 0xbf58476d1ce4e5b9ULL;
101 hash *= 0x94d049bb133111ebULL;
115 if (!router)
return NULL;
162 if (!router || !path || !handler)
return;
170 route->handler = handler;
174 route->is_wildcard =
false;
178 size_t path_len =
strlen(path);
180 route->is_wildcard = (path_len > 0 && path[path_len - 1] ==
'*');
182 if (
route->is_wildcard) {
185 }
else if (
route->is_parametric) {
189 cwist_mux_signature
signature = cwist_mux_signature_from_path(method, path);
193 size_t idx = cwist_mux_bucket_index(router, &
signature);
210static bool match_parametric_route(
const char *
route_tmpl,
const char *req_path,
213 const char *
p = req_path;
234 }
else if (*
t == *
p) {
244 if (*
t ==
'/' && *(
t + 1) ==
'\0')
t++;
245 if (*
p ==
'/' && *(
p + 1) ==
'\0')
p++;
247 if (*
t ==
'\0' && *
p ==
'\0') {
263static bool match_wildcard_route(
const char *
route_tmpl,
const char *req_path) {
286 if (state->current) {
288 state->current =
mw->
next;
289 mw->
func(req, res, mux_chain_next);
291 state->handler(req, res);
313 mux_chain_next(req, res);
327 if (!router || !path)
return NULL;
328 cwist_mux_signature
signature = cwist_mux_signature_from_path(method, path);
329 size_t idx = cwist_mux_bucket_index(router, &
signature);
341 if (
curr->method == method &&
curr->path &&
curr->path->data) {
343 if (match_parametric_route(
curr->path->data, path, &
dummy)) {
362 if (!router || !prefix)
return NULL;
367 if (!
group->prefix) {
398 if (!
group || !
group->router || !path || !handler)
return;
400 size_t path_len =
strlen(path);
425 route->middleware = node;
436 if (!router || !req || !res)
return false;
439 cwist_mux_signature
signature = cwist_mux_signature_from_path(req->
method, path);
440 size_t idx = cwist_mux_bucket_index(router, &
signature);
448 if (
curr->middleware) {
449 run_middleware_chain(
curr->middleware, req, res,
curr->handler);
451 curr->handler(req, res);
470 if (
curr->middleware) {
471 run_middleware_chain(
curr->middleware, req, res,
curr->handler);
473 curr->handler(req, res);
485 if (match_wildcard_route(
curr->path->data, path)) {
486 if (
curr->middleware) {
487 run_middleware_chain(
curr->middleware, req, res,
curr->handler);
489 curr->handler(req, res);
Memory allocation wrappers backed by libttak.
void cwist_free(void *ptr)
Free memory obtained via cwist_alloc/cwist_strdup/etc.
#define CWIST_DEFER_FREE
Attach to a pointer variable's declaration to cwist_free() it automatically when that variable's encl...
void * cwist_alloc_array(size_t count, size_t elem_size)
Allocate zeroed memory for count elements.
void * cwist_alloc(size_t size)
Allocate zeroed memory tracked by libttak.
cwist_sstring * cwist_sstring_create(void)
Create a new sstring instance.
cwist_error_t cwist_sstring_assign(cwist_sstring *str, const char *data)
Assign a C string.
void cwist_sstring_destroy(cwist_sstring *str)
Destroy an sstring instance.
void cwist_mux_route_use(cwist_mux_route *route, cwist_middleware_func mw)
Attach a middleware callback to a route, applied only when that route is served.
void cwist_mux_group_destroy(cwist_mux_group *group)
Destroy a route group and its stored prefix string.
bool cwist_mux_serve(cwist_mux_router *router, cwist_http_request *req, cwist_http_response *res)
Attempt to dispatch an incoming request through the mux table.
void cwist_mux_handle(cwist_mux_router *router, cwist_http_method_t method, const char *path, cwist_http_handler_func handler)
Register a concrete method/path pair inside the mux buckets.
cwist_mux_route * cwist_mux_find_route(cwist_mux_router *router, cwist_http_method_t method, const char *path)
Look up a registered route for a method/path pair without dispatching to it.
cwist_mux_router * cwist_mux_router_create(void)
Create an empty mux router with the default bucket fan-out.
cwist_mux_group * cwist_mux_group_create(cwist_mux_router *router, const char *prefix)
Create a route group that registers all its handlers under a shared path prefix.
void cwist_mux_group_handle(cwist_mux_group *group, cwist_http_method_t method, const char *path, cwist_http_handler_func handler)
Register a method/path handler on the router, prefixed by the group's prefix.
void cwist_mux_router_destroy(cwist_mux_router *router)
Destroy a mux router and all registered route records.
#define CWIST_MUX_DEFAULT_BUCKETS
void(* cwist_http_handler_func)(cwist_http_request *req, cwist_http_response *res)
HTTP Protocol Definitions and Helpers.
HTTP request multiplexer (router).
void cwist_query_map_set(cwist_query_map *map, const char *key, const char *value)
Set a key-value pair.
cwist_query_map * cwist_query_map_create(void)
Create a new query map.
void cwist_query_map_destroy(cwist_query_map *map)
Destroy a query map.
cwist_sstring * path
e.g., "/users/1"
void * route_middleware_state
Router middleware chain state (internal).
cwist_query_map * path_params
Parsed path parameters (e.g. :id)
cwist_http_method_t method
HTTP Response Object. Supports standard string body or Zero-Copy pointer body.
cwist_mux_router * router
cwist_middleware_func func
struct cwist_mux_middleware_node * next
struct cwist_mux_route * next
Used for global cleanup.
struct cwist_mux_route * param_next
Used for parametric routes.
cwist_http_method_t method
struct cwist_mux_route * bucket_next
Used for exact matches.
cwist_mux_route * param_routes
Head of the parametric routes list.
cwist_mux_route ** buckets
cwist_mux_route * wildcard_routes
Head of wildcard routes list.
char * data
Access directly only when raw handling is necessary.
void(* cwist_middleware_func)(cwist_http_request *req, cwist_http_response *res, cwist_handler_func next)
Middleware type that receives req/res pair and the next stage in the chain.