2 Module N_HTTP_ROUTER
gullradriel edited this page 2026-10-29 20:54:40 +01:00

HTTP ROUTER: route tables, typed placeholders, specificity

Structures

Name
struct N_ROUTE_MATCH
a successful match: the route and its decoded placeholder values
struct N_ROUTE
one route of a table

Types

Name
typedef int(*)(void *ctx, const struct N_ROUTE_MATCH *match) n_route_handler
a route handler: ctx is the caller's request context
enum N_ROUTER_RESULT { N_ROUTER_NOT_FOUND = 1, N_ROUTER_METHOD_NOT_ALLOWED = 2, N_ROUTER_FOUND = 0, N_ROUTER_BAD_REQUEST = 3}
result of n_router_match()

Functions

Name
const N_ROUTE * n_router_route(const N_ROUTER * r, size_t i)
the i-th route added (to check caller policies at start-up)
N_ROUTER * n_router_new(void )
new, empty router
N_ROUTER_RESULT n_router_match(const N_ROUTER * r, n_http_req_method method, const char * path, size_t len, N_ROUTE_MATCH * match, unsigned * allowed)
find the route for a method and a path
void n_router_free(N_ROUTER ** r)
free a router and set *r to NULL (the route tables are not touched)
size_t n_router_count(const N_ROUTER * r)
number of routes added
int n_router_check(const N_ROUTER * r, char * err, size_t errsz)
refuse ambiguous routes: two routes sharing a method that can match the same path with the same specificity
int n_router_allow_header(unsigned allowed, char * out, size_t size)
write an Allow header value ("GET, HEAD, POST") for a method mask
int n_router_add(N_ROUTER * r, const N_ROUTE * routes, size_t count)
compile and add a route table
const char * n_route_param(const N_ROUTE_MATCH * m, const char * name, size_t * len)
decoded value of a placeholder

Defines

Name
N_ROUTE_POST
route accepts POST
N_ROUTE_PARAMS_MAX
most placeholders in one route
N_ROUTE_NAME_MAX
longest placeholder name
N_ROUTE_HEAD
route accepts HEAD only (rare: GET routes answer HEAD already)
N_ROUTE_GET
route accepts GET (and so HEAD)

Types Documentation

typedef n_route_handler

typedef int(* n_route_handler) (void *ctx, const struct N_ROUTE_MATCH *match);

a route handler: ctx is the caller's request context

enum N_ROUTER_RESULT

Enumerator Value Description
N_ROUTER_NOT_FOUND 1 no route matches the path: 404 or a fallback
N_ROUTER_METHOD_NOT_ALLOWED 2 the path matches, the method does not: 405
N_ROUTER_FOUND 0 a route matched path and method
N_ROUTER_BAD_REQUEST 3 the path itself is invalid: 400

result of n_router_match()

Functions Documentation

function n_router_route

const N_ROUTE * n_router_route(
    const N_ROUTER * r,
    size_t i
)

the i-th route added (to check caller policies at start-up)

Parameters:

Return:

  • the route, NULL when out of range
  • the route, NULL when out of range

the i-th route added

the i-th route added (to check caller policies at start-up)

function n_router_new

N_ROUTER * n_router_new(
    void 
)

new, empty router

Return: the router, NULL on allocation failure

function n_router_match

N_ROUTER_RESULT n_router_match(
    const N_ROUTER * r,
    n_http_req_method method,
    const char * path,
    size_t len,
    N_ROUTE_MATCH * match,
    unsigned * allowed
)

find the route for a method and a path

Parameters:

  • r the router
  • method the request method
  • path the raw path, without the query string (leading '/')
  • len its length (at most N_HTTP_REQ_PATH_MAX)
  • match filled on N_ROUTER_FOUND
  • allowed receives, on N_ROUTER_METHOD_NOT_ALLOWED, the methods the path accepts (may be NULL)
  • r the router
  • method the request method
  • path the raw path, without the query string (leading '/')
  • len its length (at most N_HTTP_REQ_PATH_MAX)
  • match filled on N_ROUTER_FOUND
  • allowed receives the methods the path accepts on N_ROUTER_METHOD_NOT_ALLOWED (may be NULL)

Return:

function n_router_free

void n_router_free(
    N_ROUTER ** r
)

free a router and set *r to NULL (the route tables are not touched)

Parameters:

  • r address of the router pointer (may point to NULL)

function n_router_count

size_t n_router_count(
    const N_ROUTER * r
)

number of routes added

Parameters:

  • r the router

Return: the count, 0 on NULL

function n_router_check

int n_router_check(
    const N_ROUTER * r,
    char * err,
    size_t errsz
)

refuse ambiguous routes: two routes sharing a method that can match the same path with the same specificity

Parameters:

  • r the router
  • err receives a description of the first ambiguity (may be NULL)
  • errsz size of err
  • r the router
  • err receives a description of the first ambiguity (may be NULL)
  • errsz size of err

Return:

  • TRUE when no two routes are ambiguous
  • TRUE when no two routes are ambiguous

refuse two routes sharing a method that can match the same path with the same specificity

refuse ambiguous routes: two routes sharing a method that can match the same path with the same specificity

function n_router_allow_header

int n_router_allow_header(
    unsigned allowed,
    char * out,
    size_t size
)

write an Allow header value ("GET, HEAD, POST") for a method mask

Parameters:

  • allowed the mask (GET implies HEAD)
  • out destination
  • size its size (24 bytes always suffice)
  • allowed the mask
  • out destination
  • size its size

Return:

  • TRUE, FALSE when out is NULL or too small
  • TRUE, FALSE when out is NULL or too small

write an Allow header value for a method mask (GET implies HEAD)

write an Allow header value ("GET, HEAD, POST") for a method mask

function n_router_add

int n_router_add(
    N_ROUTER * r,
    const N_ROUTE * routes,
    size_t count
)

compile and add a route table

Parameters:

  • r the router
  • routes the table, kept by pointer (must outlive the router)
  • count number of routes
  • r the router
  • routes the table, kept by pointer (must outlive the router)
  • count number of routes

Return:

  • TRUE, FALSE when a route is refused
  • TRUE, FALSE when a route is refused

compile and add a route table; nothing is added when a route is refused

Every pattern is validated: a leading '/', no empty segment, no '', literal bytes visible ASCII, placeholders well-formed with a known type, unique names of at most N_ROUTE_NAME_MAX of [a-z0-9_], at most N_ROUTE_PARAMS_MAX of them, rest only last and without a trailing '/'. A route without a method or a handler is refused too. On failure nothing of this table is added and the offending pattern is logged. compile and add a route table

function n_route_param

const char * n_route_param(
    const N_ROUTE_MATCH * m,
    const char * name,
    size_t * len
)

decoded value of a placeholder

Parameters:

  • m the match
  • name the placeholder name
  • len receives the length (may be NULL)

Return: the value, or NULL when the route has no such placeholder

Macros Documentation

define N_ROUTE_POST

#define N_ROUTE_POST N_HTTP_REQ_METHOD_BIT(N_HTTP_REQ_POST)

route accepts POST

define N_ROUTE_PARAMS_MAX

#define N_ROUTE_PARAMS_MAX 8

most placeholders in one route

define N_ROUTE_NAME_MAX

#define N_ROUTE_NAME_MAX 31

longest placeholder name

define N_ROUTE_HEAD

#define N_ROUTE_HEAD N_HTTP_REQ_METHOD_BIT(N_HTTP_REQ_HEAD)

route accepts HEAD only (rare: GET routes answer HEAD already)

define N_ROUTE_GET

#define N_ROUTE_GET N_HTTP_REQ_METHOD_BIT(N_HTTP_REQ_GET)

route accepts GET (and so HEAD)