feat(lnm): add request parser
ci/woodpecker/push/build Pipeline was successful
Details
ci/woodpecker/push/build Pipeline was successful
Details
parent
e59ee38ae2
commit
4c2b85d436
|
@ -12,7 +12,7 @@ typedef enum lnm_http_method {
|
||||||
http_method_put,
|
http_method_put,
|
||||||
http_method_patch,
|
http_method_patch,
|
||||||
http_method_delete
|
http_method_delete
|
||||||
} http_method;
|
} lnm_http_method;
|
||||||
|
|
||||||
extern const char *lnm_http_status_names[][32];
|
extern const char *lnm_http_status_names[][32];
|
||||||
|
|
||||||
|
|
|
@ -3,9 +3,11 @@
|
||||||
|
|
||||||
#include "lnm/common.h"
|
#include "lnm/common.h"
|
||||||
|
|
||||||
|
#define LNM_HTTP_MAX_REQ_HEADERS 32
|
||||||
|
|
||||||
typedef struct lnm_loop lnm_http_loop;
|
typedef struct lnm_loop lnm_http_loop;
|
||||||
|
|
||||||
typedef struct lnm_http_conn lnm_http_conn;
|
typedef struct lnm_conn lnm_http_conn;
|
||||||
|
|
||||||
typedef struct lnm_http_step lnm_http_step;
|
typedef struct lnm_http_step lnm_http_step;
|
||||||
|
|
||||||
|
@ -20,14 +22,6 @@ typedef lnm_err (*lnm_http_step_fn)(lnm_http_conn *conn);
|
||||||
*/
|
*/
|
||||||
lnm_err lnm_http_loop_init(lnm_http_loop **out);
|
lnm_err lnm_http_loop_init(lnm_http_loop **out);
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize a first step
|
|
||||||
*
|
|
||||||
* @param out where to store pointer to new `lnm_http_step`
|
|
||||||
* @param fn step function associated with the step
|
|
||||||
*/
|
|
||||||
lnm_err lnm_http_step_init(lnm_http_step **out, lnm_http_step_fn fn);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append the given step fn to the step.
|
* Append the given step fn to the step.
|
||||||
*
|
*
|
||||||
|
@ -67,4 +61,15 @@ lnm_err lnm_http_route_init_regex(lnm_http_route **out, const char *pattern,
|
||||||
*/
|
*/
|
||||||
void lnm_http_loop_route_add(lnm_http_loop *hl, lnm_http_route *route);
|
void lnm_http_loop_route_add(lnm_http_loop *hl, lnm_http_route *route);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents what state an HTTP loop request is currently in.
|
||||||
|
*/
|
||||||
|
typedef enum lnm_http_loop_state {
|
||||||
|
lnm_http_loop_state_parse_req = 0,
|
||||||
|
} lnm_http_loop_state;
|
||||||
|
|
||||||
|
typedef struct lnm_http_loop_ctx {
|
||||||
|
lnm_http_loop_state state;
|
||||||
|
} lnm_http_loop_ctx;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef LNM_HTTP_REQ
|
||||||
|
#define LNM_HTTP_REQ
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "picohttpparser.h"
|
||||||
|
|
||||||
|
#include "lnm/http/consts.h"
|
||||||
|
#include "lnm/http/loop.h"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents the parsed HTTP request
|
||||||
|
*/
|
||||||
|
typedef struct lnm_http_req {
|
||||||
|
size_t len;
|
||||||
|
int minor_version;
|
||||||
|
lnm_http_method method;
|
||||||
|
struct {
|
||||||
|
const char *s;
|
||||||
|
size_t len;
|
||||||
|
} path;
|
||||||
|
struct {
|
||||||
|
const char *s;
|
||||||
|
size_t len;
|
||||||
|
} query;
|
||||||
|
struct {
|
||||||
|
struct phr_header arr[LNM_HTTP_MAX_REQ_HEADERS];
|
||||||
|
size_t len;
|
||||||
|
} headers;
|
||||||
|
} lnm_http_req;
|
||||||
|
|
||||||
|
typedef enum lnm_http_parse_err {
|
||||||
|
lnm_http_parse_err_ok = 0,
|
||||||
|
lnm_http_parse_err_incomplete,
|
||||||
|
lnm_http_parse_err_invalid,
|
||||||
|
lnm_http_parse_err_unknown_method,
|
||||||
|
} lnm_http_parse_err;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Try to parse the given buffer into an HTTP request.
|
||||||
|
*
|
||||||
|
* @param req request to store parsed data in
|
||||||
|
* @param buf buffer to parse; might be modified
|
||||||
|
* @param len length of buf
|
||||||
|
*/
|
||||||
|
lnm_http_parse_err lnm_http_req_parse(lnm_http_req *req, char *buf, size_t len);
|
||||||
|
|
||||||
|
#endif
|
|
@ -5,10 +5,6 @@
|
||||||
|
|
||||||
#include "lnm/http/loop.h"
|
#include "lnm/http/loop.h"
|
||||||
|
|
||||||
typedef struct lnm_http_conn {
|
|
||||||
|
|
||||||
} lnm_http_conn;
|
|
||||||
|
|
||||||
typedef struct lnm_http_step {
|
typedef struct lnm_http_step {
|
||||||
lnm_http_step_fn fn;
|
lnm_http_step_fn fn;
|
||||||
struct lnm_http_step *next;
|
struct lnm_http_step *next;
|
||||||
|
@ -29,6 +25,19 @@ typedef struct lnm_http_route {
|
||||||
lnm_http_step *step;
|
lnm_http_step *step;
|
||||||
} lnm_http_route;
|
} lnm_http_route;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a new empty route.
|
||||||
|
*
|
||||||
|
* @param out where to store pointer to new `lnm_http_route`
|
||||||
|
*/
|
||||||
lnm_err lnm_http_route_init(lnm_http_route **out);
|
lnm_err lnm_http_route_init(lnm_http_route **out);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize a first step.
|
||||||
|
*
|
||||||
|
* @param out where to store pointer to new `lnm_http_step`
|
||||||
|
* @param fn step function associated with the step
|
||||||
|
*/
|
||||||
|
lnm_err lnm_http_step_init(lnm_http_step **out, lnm_http_step_fn fn);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "lnm/http/consts.h"
|
||||||
|
#include "lnm/http/loop.h"
|
||||||
|
#include "lnm/http/req.h"
|
||||||
|
|
||||||
|
lnm_http_parse_err lnm_http_req_parse(lnm_http_req *req, char *buf,
|
||||||
|
size_t len) {
|
||||||
|
const char *method;
|
||||||
|
char *path;
|
||||||
|
size_t method_len, path_len;
|
||||||
|
|
||||||
|
req->headers.len = LNM_HTTP_MAX_REQ_HEADERS;
|
||||||
|
|
||||||
|
int req_len = phr_parse_request(
|
||||||
|
buf, len, &method, &method_len, (const char **)&path, &path_len,
|
||||||
|
&req->minor_version, req->headers.arr, &req->headers.len, 0);
|
||||||
|
|
||||||
|
if (req_len == -1) {
|
||||||
|
return lnm_http_parse_err_invalid;
|
||||||
|
} else if (req_len == -2) {
|
||||||
|
return lnm_http_parse_err_incomplete;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool known_method = false;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < lnm_http_method_names_len && !known_method; i++) {
|
||||||
|
if (strncmp(method, lnm_http_method_names[i], method_len) == 0) {
|
||||||
|
req->method = i;
|
||||||
|
known_method = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!known_method) {
|
||||||
|
return lnm_http_parse_err_unknown_method;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *question_mark = strchr(path, '?');
|
||||||
|
|
||||||
|
// Only store query if the path doesn't simply end with a question mark
|
||||||
|
if ((question_mark != NULL) && (path_len - (question_mark + 1 - path) > 0)) {
|
||||||
|
req->query.s = question_mark + 1;
|
||||||
|
req->query.len = path_len - (question_mark + 1 - path);
|
||||||
|
|
||||||
|
path_len = question_mark - path;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All parsed strings should be null-terminated. This character is either a
|
||||||
|
// newline (if at the end of the path), or a question mark (if a query is
|
||||||
|
// present).
|
||||||
|
path[path_len] = '\0';
|
||||||
|
req->path.len = path_len;
|
||||||
|
req->path.s = path;
|
||||||
|
req->len = req_len;
|
||||||
|
|
||||||
|
return lnm_http_parse_err_ok;
|
||||||
|
}
|
Loading…
Reference in New Issue