57 lines
1.7 KiB
C
57 lines
1.7 KiB
C
#include "http_loop.h"
|
|
#include "http.h"
|
|
|
|
bool http_loop_handle_request(event_loop_conn *conn) {
|
|
// Prevents the request handler function from looping indefinitely without
|
|
// ever consuming new data
|
|
if (conn->rbuf_size - conn->rbuf_read == 0) {
|
|
return false;
|
|
}
|
|
|
|
http_loop_ctx *ctx = conn->ctx;
|
|
|
|
// If route is defined, we're currently processing a request
|
|
if (ctx->route == NULL) {
|
|
http_parse_error res = http_loop_parse_request(conn);
|
|
|
|
if (res == http_parse_error_invalid ||
|
|
(res == http_parse_error_incomplete &&
|
|
conn->rbuf_size == EVENT_LOOP_BUFFER_SIZE)) {
|
|
conn->state = event_loop_conn_state_end;
|
|
|
|
return false;
|
|
}
|
|
|
|
conn->rbuf_read += ctx->req.len;
|
|
|
|
// It's fun to respond with extremely specific error messages
|
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/501
|
|
if (res == http_parse_error_unknown_method) {
|
|
ctx->res.type = http_method_not_implemented;
|
|
conn->state = event_loop_conn_state_res;
|
|
} else {
|
|
http_loop_route_request(conn);
|
|
}
|
|
}
|
|
|
|
if (conn->state == event_loop_conn_state_req) {
|
|
http_loop_process_request(conn);
|
|
}
|
|
|
|
// TODO in highly concurrent situations, it might actually be better to always
|
|
// return false here, as this allows cycling better through all connections
|
|
return conn->state == event_loop_conn_state_req;
|
|
}
|
|
|
|
event_loop *http_loop_init(http_loop_gctx *gctx) {
|
|
event_loop *el = event_loop_init();
|
|
|
|
el->ctx_init = (void *(*)(void *))http_loop_ctx_init;
|
|
el->ctx_free = (void (*)(void *))http_loop_ctx_free;
|
|
el->handle_data = http_loop_handle_request;
|
|
el->write_data = http_loop_write_response;
|
|
el->gctx = gctx;
|
|
|
|
return el;
|
|
}
|