feat: parse method into enum value

c-web-server
Jef Roosens 2023-05-28 09:09:46 +02:00
parent 90ff55d977
commit a90330dd6e
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
5 changed files with 50 additions and 10 deletions

View File

@ -15,6 +15,8 @@ extern const char http_405[];
extern const size_t http_405_len; extern const size_t http_405_len;
extern const char http_500[]; extern const char http_500[];
extern const size_t http_500_len; extern const size_t http_500_len;
extern const char http_501[];
extern const size_t http_501_len;
typedef enum http_request_method { typedef enum http_request_method {
http_request_method_get = 0, http_request_method_get = 0,
@ -24,14 +26,16 @@ typedef enum http_request_method {
http_request_method_delete = 4 http_request_method_delete = 4
} http_request_method; } http_request_method;
extern const char *request_method_names[];
extern const size_t request_method_names_len;
/* /*
* Struct representing the specific type of request * Struct representing the specific type of request
*/ */
typedef struct http_request { typedef struct http_request {
size_t len; size_t len;
int minor_version; int minor_version;
const char *method; http_request_method method;
size_t method_len;
const char *path; const char *path;
size_t path_len; size_t path_len;
const char *query; const char *query;
@ -43,13 +47,15 @@ typedef enum http_parse_error {
http_parse_error_ok = 0, http_parse_error_ok = 0,
http_parse_error_incomplete = 1, http_parse_error_incomplete = 1,
http_parse_error_invalid = 2, http_parse_error_invalid = 2,
http_parse_error_unknown_method = 3
} http_parse_error; } http_parse_error;
/* void http_route(event_loop_conn *conn); */ /* void http_route(event_loop_conn *conn); */
typedef enum http_response_type { typedef enum http_response_type {
http_not_found = 404, http_not_found = 404,
http_method_not_allowed = 405 http_method_not_allowed = 405,
http_method_not_implemented = 501
} http_response_type; } http_response_type;
void http_write_standard_response(event_loop_conn *conn, void http_write_standard_response(event_loop_conn *conn,

View File

@ -36,6 +36,12 @@ bool http_loop_handle_request(event_loop_conn *conn) {
return false; return false;
} }
// It's fun to respond with extremely specific error messages
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/501
else if (res == http_parse_error_unknown_method) {
http_write_standard_response(conn, 501);
return false;
}
conn->rbuf_read += res; conn->rbuf_read += res;

View File

@ -11,3 +11,11 @@ const size_t http_405_len = sizeof(http_405) - 1;
const char http_500[] = "HTTP/1.1 500 Internal Server Error\n" const char http_500[] = "HTTP/1.1 500 Internal Server Error\n"
"Content-Length: 0\n\n"; "Content-Length: 0\n\n";
const size_t http_500_len = sizeof(http_500) - 1; const size_t http_500_len = sizeof(http_500) - 1;
const char http_501[] = "HTTP/1.1 501 Not Implemented\n"
"Content-Length: 0\n\n";
const size_t http_501_len = sizeof(http_501) - 1;
// Very important that this is in the same order as http_request_method
const char *request_method_names[] = {"GET", "POST", "PUT", "PATCH", "DELETE"};
const size_t request_method_names_len =
sizeof(request_method_names) / sizeof(request_method_names[0]);

View File

@ -10,11 +10,13 @@ http_parse_error http_loop_parse_request(event_loop_conn *conn) {
size_t num_headers = HTTP_MAX_ALLOWED_HEADERS; size_t num_headers = HTTP_MAX_ALLOWED_HEADERS;
http_request *req = &ctx->req; http_request *req = &ctx->req;
int res = const char *method;
phr_parse_request((const char *)&conn->rbuf[conn->rbuf_read], size_t method_len;
conn->rbuf_size - conn->rbuf_read, &req->method,
&req->method_len, &req->path, &req->path_len, int res = phr_parse_request(
&req->minor_version, req->headers, &num_headers, 0); (const char *)&conn->rbuf[conn->rbuf_read],
conn->rbuf_size - conn->rbuf_read, &method, &method_len, &req->path,
&req->path_len, &req->minor_version, req->headers, &num_headers, 0);
if (res == -1) { if (res == -1) {
return http_parse_error_invalid; return http_parse_error_invalid;
@ -24,8 +26,23 @@ http_parse_error http_loop_parse_request(event_loop_conn *conn) {
req->len = res; req->len = res;
// Split path into path & query // Try to parse the method type
bool match = false;
size_t i = 0; size_t i = 0;
for (i = 0; i < request_method_names_len; i++) {
if (strncmp(method, request_method_names[i], method_len) == 0) {
req->method = i;
match = true;
}
}
if (!match) {
return http_parse_error_unknown_method;
}
// Split path into path & query
i = 0;
bool no_query = true; bool no_query = true;
while (no_query && i < req->path_len) { while (no_query && i < req->path_len) {
@ -77,7 +94,7 @@ bool http_loop_route_request(event_loop_conn *conn) {
http_loop_ctx *ctx = conn->ctx; http_loop_ctx *ctx = conn->ctx;
http_loop_gctx *gctx = ctx->g; http_loop_gctx *gctx = ctx->g;
info("%.*s %.*s", ctx->req.method_len, ctx->req.method, ctx->req.path_len, info("%s %.*s", request_method_names[ctx->req.method], ctx->req.path_len,
ctx->req.path); ctx->req.path);
http_route *route; http_route *route;

View File

@ -14,6 +14,9 @@ void http_write_standard_response(event_loop_conn *conn,
case 405: case 405:
s = http_405; s = http_405;
len = http_405_len; len = http_405_len;
case 501:
s = http_501;
len = http_501_len;
} }
memcpy(conn->wbuf, s, len); memcpy(conn->wbuf, s, len);