feat: routes now specify a method

c-web-server
Jef Roosens 2023-05-29 12:43:50 +02:00
parent 9b66223a57
commit 18d67fb69f
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
8 changed files with 40 additions and 17 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ compile_commands.json
lander.data* lander.data*
pastes/ pastes/
.cache/ .cache/
vgcore.*

View File

@ -11,11 +11,11 @@
extern const char *http_response_type_names[5][32]; extern const char *http_response_type_names[5][32];
typedef enum http_request_method { typedef enum http_request_method {
http_request_method_get = 0, http_get = 0,
http_request_method_post = 1, http_post = 1,
http_request_method_put = 2, http_put = 2,
http_request_method_patch = 3, http_patch = 3,
http_request_method_delete = 4 http_delete = 4
} http_request_method; } http_request_method;
extern const char *request_method_names[]; extern const char *request_method_names[];

View File

@ -14,6 +14,7 @@ typedef enum http_route_type {
typedef struct http_route { typedef struct http_route {
http_route_type type; http_route_type type;
http_request_method method;
char *path; char *path;
regex_t *regex; regex_t *regex;
bool (*steps[5])(event_loop_conn *); bool (*steps[5])(event_loop_conn *);
@ -93,7 +94,8 @@ void http_loop_process_request(event_loop_conn *conn);
* Set the request body to the given buffer. If owned is set to true, the body * Set the request body to the given buffer. If owned is set to true, the body
* buffer will be free'd after the request has finished. * buffer will be free'd after the request has finished.
*/ */
void http_loop_res_set_body(const char *body, size_t body_len, bool owned); void http_loop_res_set_body(http_loop_ctx *ctx, const char *body,
size_t body_len, bool owned);
/** /**
* Initialize a new http loop * Initialize a new http loop

View File

@ -3,6 +3,7 @@
// clang-format off // clang-format off
const char *http_response_type_names[5][32] = { const char *http_response_type_names[5][32] = {
// 1xx
{ {
"Continue", // 100 "Continue", // 100
"Switching Protocols", // 101, "Switching Protocols", // 101,

View File

@ -35,6 +35,7 @@ void http_loop_ctx_reset(http_loop_ctx *ctx) {
ctx->res.body = NULL; ctx->res.body = NULL;
ctx->res.type = 0;
ctx->res.head_len = 0; ctx->res.head_len = 0;
ctx->res.head_written = 0; ctx->res.head_written = 0;
ctx->res.body_len = 0; ctx->res.body_len = 0;

View File

@ -79,6 +79,7 @@ void http_loop_route_request(event_loop_conn *conn) {
ctx->req.path); ctx->req.path);
http_route *route; http_route *route;
bool path_matched = false;
for (size_t i = 0; i < gctx->route_count; i++) { for (size_t i = 0; i < gctx->route_count; i++) {
route = &gctx->routes[i]; route = &gctx->routes[i];
@ -86,16 +87,21 @@ void http_loop_route_request(event_loop_conn *conn) {
switch (route->type) { switch (route->type) {
case http_route_literal: case http_route_literal:
if (strncmp(route->path, ctx->req.path, ctx->req.path_len) == 0) { if (strncmp(route->path, ctx->req.path, ctx->req.path_len) == 0) {
ctx->route = route; path_matched = true;
return;
if (ctx->req.method == route->method) {
ctx->route = route;
return;
}
} }
break;
// TODO // TODO
case http_route_regex:; case http_route_regex:;
} }
} }
// Fallthrough is to write a 404 // Fallthrough case
ctx->res.type = http_not_found; ctx->res.type = path_matched ? http_method_not_allowed : http_not_found;
conn->state = event_loop_conn_state_res; conn->state = event_loop_conn_state_res;
} }

View File

@ -9,6 +9,10 @@ static const char *http_response_format = "HTTP/1.1 %i %s\n"
"Content-Length: %lu\n\n"; "Content-Length: %lu\n\n";
void http_loop_init_header(http_response *res) { void http_loop_init_header(http_response *res) {
if (res->type == 0) {
res->type = http_ok;
}
const char *response_type_name = const char *response_type_name =
http_response_type_names[res->type / 100 - 1][res->type % 100]; http_response_type_names[res->type / 100 - 1][res->type % 100];
@ -61,3 +65,10 @@ void http_loop_write_response(event_loop_conn *conn) {
res->body_written += bytes_to_write; res->body_written += bytes_to_write;
} }
} }
void http_loop_res_set_body(http_loop_ctx *ctx, const char *body,
size_t body_len, bool owned) {
ctx->res.body = body;
ctx->res.body_len = body_len;
ctx->res.owns_body = owned;
}

View File

@ -14,19 +14,20 @@ const char index_page[] =
" </body>\n" " </body>\n"
"</html>\n"; "</html>\n";
bool http_write_404(event_loop_conn *conn) { bool lander_get_index(event_loop_conn *conn) {
http_loop_ctx *ctx = conn->ctx; http_loop_ctx *ctx = conn->ctx;
ctx->res.type = 200;
ctx->res.body = index_page; http_loop_res_set_body(ctx, index_page, sizeof(index_page) - 1, false);
ctx->res.body_len = sizeof(index_page) - 1;
ctx->res.owns_body = false;
conn->state = event_loop_conn_state_res; conn->state = event_loop_conn_state_res;
return true; return true;
} }
http_route routes[] = { http_route routes[] = {{.type = http_route_literal,
{.type = http_route_literal, .path = "/", .steps = {http_write_404, NULL}}}; .method = http_get,
.path = "/",
.steps = {lander_get_index, NULL}}};
int main() { int main() {
setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stdout, NULL, _IONBF, 0);