feat(routing): make path segments easily accessible from request struct
parent
fbd41f7e4e
commit
3ae1b62dd0
|
@ -1,5 +1,6 @@
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "lnm/http/req.h"
|
||||||
#include "lnm/log.h"
|
#include "lnm/log.h"
|
||||||
#include "lnm/loop.h"
|
#include "lnm/loop.h"
|
||||||
#include "lnm/http/loop.h"
|
#include "lnm/http/loop.h"
|
||||||
|
@ -16,8 +17,9 @@ void ctx_free(void *c_ctx) {}
|
||||||
lnm_http_step_err print_step(lnm_http_conn *conn) {
|
lnm_http_step_err print_step(lnm_http_conn *conn) {
|
||||||
lnm_http_loop_ctx *ctx = conn->ctx;
|
lnm_http_loop_ctx *ctx = conn->ctx;
|
||||||
|
|
||||||
const lnm_http_route_match_segment *seg = lnm_http_route_match_get(&ctx->match, "key");
|
const char *key;
|
||||||
lnm_linfo("main", "key: %.*s", seg->len, ctx->req.buf.s + ctx->req.path.o + seg->start);
|
size_t key_len = lnm_http_req_route_segment(&key, &ctx->req, "key") ;
|
||||||
|
lnm_linfo("main", "key: %.*s", key_len, key);
|
||||||
return lnm_http_step_err_done;
|
return lnm_http_step_err_done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,17 +6,7 @@
|
||||||
#include "lnm/common.h"
|
#include "lnm/common.h"
|
||||||
#include "lnm/http/req.h"
|
#include "lnm/http/req.h"
|
||||||
#include "lnm/http/res.h"
|
#include "lnm/http/res.h"
|
||||||
|
#include "lnm/http/route.h"
|
||||||
#define LNM_HTTP_MAX_KEY_SEGMENTS 4
|
|
||||||
|
|
||||||
typedef enum lnm_http_step_err {
|
|
||||||
lnm_http_step_err_done = 0,
|
|
||||||
lnm_http_step_err_io_needed,
|
|
||||||
lnm_http_step_err_close,
|
|
||||||
lnm_http_step_err_res,
|
|
||||||
} lnm_http_step_err;
|
|
||||||
|
|
||||||
typedef lnm_http_step_err (*lnm_http_step_fn)(lnm_http_conn *conn);
|
|
||||||
|
|
||||||
typedef lnm_err (*lnm_http_ctx_init_fn)(void **c_ctx, void *gctx);
|
typedef lnm_err (*lnm_http_ctx_init_fn)(void **c_ctx, void *gctx);
|
||||||
|
|
||||||
|
@ -24,55 +14,6 @@ typedef void (*lnm_http_ctx_reset_fn)(void *c_ctx);
|
||||||
|
|
||||||
typedef void (*lnm_http_ctx_free_fn)(void *c_ctx);
|
typedef void (*lnm_http_ctx_free_fn)(void *c_ctx);
|
||||||
|
|
||||||
typedef struct lnm_http_route lnm_http_route;
|
|
||||||
|
|
||||||
typedef struct lnm_http_route_match_segment {
|
|
||||||
size_t start;
|
|
||||||
size_t len;
|
|
||||||
} lnm_http_route_match_segment;
|
|
||||||
|
|
||||||
typedef struct lnm_http_route_match {
|
|
||||||
const lnm_http_route *route;
|
|
||||||
lnm_http_method method;
|
|
||||||
lnm_http_route_match_segment key_segments[LNM_HTTP_MAX_KEY_SEGMENTS];
|
|
||||||
} lnm_http_route_match;
|
|
||||||
|
|
||||||
typedef struct lnm_http_router lnm_http_router;
|
|
||||||
|
|
||||||
typedef enum lnm_http_route_err {
|
|
||||||
lnm_http_route_err_match = 0,
|
|
||||||
lnm_http_route_err_unknown_route = 1,
|
|
||||||
lnm_http_route_err_unknown_method = 2,
|
|
||||||
} lnm_http_route_err;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Allocate and initialize a new http_router.
|
|
||||||
*/
|
|
||||||
lnm_err lnm_http_router_init(lnm_http_router **out);
|
|
||||||
|
|
||||||
void lnm_http_router_free(lnm_http_router *router);
|
|
||||||
|
|
||||||
lnm_err lnm_http_router_add(lnm_http_route **out, lnm_http_router *http_router,
|
|
||||||
lnm_http_method method, const char *path);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add all of the child router's routes to the parent router, under the given
|
|
||||||
* route prefix.
|
|
||||||
*/
|
|
||||||
lnm_err lnm_http_router_nest(lnm_http_router *parent,
|
|
||||||
const lnm_http_router *child, const char *prefix);
|
|
||||||
|
|
||||||
lnm_http_route_err lnm_http_router_route(lnm_http_route_match *out,
|
|
||||||
const lnm_http_router *router,
|
|
||||||
lnm_http_method method,
|
|
||||||
const char *path);
|
|
||||||
|
|
||||||
const lnm_http_route_match_segment *
|
|
||||||
lnm_http_route_match_get(lnm_http_route_match *match, const char *key);
|
|
||||||
|
|
||||||
lnm_err lnm_http_route_step_append(lnm_http_route *route, lnm_http_step_fn fn,
|
|
||||||
bool blocking);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a new `lnm_http_loop`.
|
* Initialize a new `lnm_http_loop`.
|
||||||
*
|
*
|
||||||
|
@ -130,7 +71,6 @@ typedef struct lnm_http_loop_ctx {
|
||||||
lnm_http_loop_state state;
|
lnm_http_loop_state state;
|
||||||
lnm_http_req req;
|
lnm_http_req req;
|
||||||
lnm_http_res res;
|
lnm_http_res res;
|
||||||
lnm_http_route_match match;
|
|
||||||
lnm_http_step *cur_step;
|
lnm_http_step *cur_step;
|
||||||
lnm_http_loop_gctx *g;
|
lnm_http_loop_gctx *g;
|
||||||
void *c;
|
void *c;
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "lnm/common.h"
|
#include "lnm/common.h"
|
||||||
#include "lnm/http/consts.h"
|
#include "lnm/http/consts.h"
|
||||||
|
#include "lnm/http/route.h"
|
||||||
|
|
||||||
#define LNM_HTTP_MAX_REQ_HEADERS 32
|
#define LNM_HTTP_MAX_REQ_HEADERS 32
|
||||||
#define LNM_HTTP_MAX_REGEX_GROUPS 4
|
#define LNM_HTTP_MAX_REGEX_GROUPS 4
|
||||||
|
@ -35,6 +36,7 @@ typedef struct lnm_http_req {
|
||||||
} buf;
|
} buf;
|
||||||
int minor_version;
|
int minor_version;
|
||||||
lnm_http_method method;
|
lnm_http_method method;
|
||||||
|
lnm_http_route_match route_match;
|
||||||
struct {
|
struct {
|
||||||
size_t o;
|
size_t o;
|
||||||
size_t len;
|
size_t len;
|
||||||
|
@ -108,4 +110,14 @@ lnm_err lnm_http_req_header_get(const char **out, size_t *out_len,
|
||||||
lnm_err lnm_http_req_header_get_s(const char **out, size_t *out_len,
|
lnm_err lnm_http_req_header_get_s(const char **out, size_t *out_len,
|
||||||
lnm_http_req *req, const char *name);
|
lnm_http_req *req, const char *name);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve a named key segment from the matched route.
|
||||||
|
*
|
||||||
|
* @param out where to write pointer to string
|
||||||
|
* @param key key of the segment
|
||||||
|
* @return length of the outputted char buffer, or 0 if the key doesn't exist
|
||||||
|
*/
|
||||||
|
size_t lnm_http_req_route_segment(const char **out, lnm_http_req *req,
|
||||||
|
const char *key);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,69 @@
|
||||||
|
#ifndef LNM_HTTP_ROUTE
|
||||||
|
#define LNM_HTTP_ROUTE
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "lnm/common.h"
|
||||||
|
#include "lnm/http/consts.h"
|
||||||
|
|
||||||
|
#define LNM_HTTP_MAX_KEY_SEGMENTS 4
|
||||||
|
|
||||||
|
typedef enum lnm_http_step_err {
|
||||||
|
lnm_http_step_err_done = 0,
|
||||||
|
lnm_http_step_err_io_needed,
|
||||||
|
lnm_http_step_err_close,
|
||||||
|
lnm_http_step_err_res,
|
||||||
|
} lnm_http_step_err;
|
||||||
|
|
||||||
|
typedef lnm_http_step_err (*lnm_http_step_fn)(lnm_http_conn *conn);
|
||||||
|
|
||||||
|
typedef struct lnm_http_route lnm_http_route;
|
||||||
|
|
||||||
|
typedef struct lnm_http_route_match_segment {
|
||||||
|
size_t start;
|
||||||
|
size_t len;
|
||||||
|
} lnm_http_route_match_segment;
|
||||||
|
|
||||||
|
typedef struct lnm_http_route_match {
|
||||||
|
const lnm_http_route *route;
|
||||||
|
lnm_http_method method;
|
||||||
|
lnm_http_route_match_segment key_segments[LNM_HTTP_MAX_KEY_SEGMENTS];
|
||||||
|
} lnm_http_route_match;
|
||||||
|
|
||||||
|
typedef struct lnm_http_router lnm_http_router;
|
||||||
|
|
||||||
|
typedef enum lnm_http_route_err {
|
||||||
|
lnm_http_route_err_match = 0,
|
||||||
|
lnm_http_route_err_unknown_route = 1,
|
||||||
|
lnm_http_route_err_unknown_method = 2,
|
||||||
|
} lnm_http_route_err;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allocate and initialize a new http_router.
|
||||||
|
*/
|
||||||
|
lnm_err lnm_http_router_init(lnm_http_router **out);
|
||||||
|
|
||||||
|
void lnm_http_router_free(lnm_http_router *router);
|
||||||
|
|
||||||
|
lnm_err lnm_http_router_add(lnm_http_route **out, lnm_http_router *http_router,
|
||||||
|
lnm_http_method method, const char *path);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add all of the child router's routes to the parent router, under the given
|
||||||
|
* route prefix.
|
||||||
|
*/
|
||||||
|
lnm_err lnm_http_router_nest(lnm_http_router *parent,
|
||||||
|
const lnm_http_router *child, const char *prefix);
|
||||||
|
|
||||||
|
lnm_http_route_err lnm_http_router_route(lnm_http_route_match *out,
|
||||||
|
const lnm_http_router *router,
|
||||||
|
lnm_http_method method,
|
||||||
|
const char *path);
|
||||||
|
|
||||||
|
const lnm_http_route_match_segment *
|
||||||
|
lnm_http_route_match_get(lnm_http_route_match *match, const char *key);
|
||||||
|
|
||||||
|
lnm_err lnm_http_route_step_append(lnm_http_route *route, lnm_http_step_fn fn,
|
||||||
|
bool blocking);
|
||||||
|
|
||||||
|
#endif
|
|
@ -58,10 +58,11 @@ void lnm_http_loop_process_route(lnm_http_conn *conn) {
|
||||||
lnm_http_loop_ctx *ctx = conn->ctx;
|
lnm_http_loop_ctx *ctx = conn->ctx;
|
||||||
const lnm_http_loop_gctx *gctx = ctx->g;
|
const lnm_http_loop_gctx *gctx = ctx->g;
|
||||||
|
|
||||||
switch (lnm_http_router_route(&ctx->match, gctx->router, ctx->req.method,
|
switch (lnm_http_router_route(&ctx->req.route_match, gctx->router,
|
||||||
|
ctx->req.method,
|
||||||
ctx->req.buf.s + ctx->req.path.o)) {
|
ctx->req.buf.s + ctx->req.path.o)) {
|
||||||
case lnm_http_route_err_match:
|
case lnm_http_route_err_match:
|
||||||
ctx->cur_step = ctx->match.route->step;
|
ctx->cur_step = ctx->req.route_match.route->step;
|
||||||
ctx->state = lnm_http_loop_state_parse_headers;
|
ctx->state = lnm_http_loop_state_parse_headers;
|
||||||
break;
|
break;
|
||||||
case lnm_http_route_err_unknown_method:
|
case lnm_http_route_err_unknown_method:
|
||||||
|
|
|
@ -112,3 +112,19 @@ lnm_err lnm_http_req_header_get_s(const char **out, size_t *out_len,
|
||||||
|
|
||||||
return lnm_err_not_found;
|
return lnm_err_not_found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t lnm_http_req_route_segment(const char **out, lnm_http_req *req,
|
||||||
|
const char *key) {
|
||||||
|
const lnm_http_route_match_segment *segment =
|
||||||
|
lnm_http_route_match_get(&req->route_match, key);
|
||||||
|
|
||||||
|
if (segment == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (out != NULL) {
|
||||||
|
*out = req->buf.s + req->path.o + segment->start;
|
||||||
|
}
|
||||||
|
|
||||||
|
return segment->len;
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue