#ifndef LANDER_HTTP_LOOP #define LANDER_HTTP_LOOP #include #include "event_loop.h" #include "http.h" #include "trie.h" #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #define MAX(x, y) (((x) > (y)) ? (x) : (y)) typedef enum http_route_type { http_route_literal = 0, http_route_regex = 1, } http_route_type; typedef struct http_route { http_route_type type; http_request_method method; char *path; regex_t *regex; bool (*steps[5])(event_loop_conn *); } http_route; /* * Global context passed to every connection using the same pointer */ typedef struct http_loop_gctx { http_route *routes; size_t route_count; Trie *trie; const char *api_key; } http_loop_gctx; /* * Initialize a new global context */ http_loop_gctx *http_loop_gctx_init(); /* * Invidivual context initialized for every connection */ typedef struct http_loop_ctx { http_request req; http_response res; http_route *route; size_t current_step; http_loop_gctx *g; } http_loop_ctx; /* * Initialize a context struct */ http_loop_ctx *http_loop_ctx_init(http_loop_gctx *g); /* * Resets an already allocated context so that it can be reused for a new * request. */ void http_loop_ctx_reset(http_loop_ctx *ctx); /* * Free a context struct */ void http_loop_ctx_free(http_loop_ctx *ctx); /* * Process incoming data as an HTTP request. This is the "handle_data" function * for the event loop. */ bool http_loop_handle_request(event_loop_conn *conn); /* * Write the HTTP response to the file descriptor. This is the "write_data" * function for the event loop. */ void http_loop_write_response(event_loop_conn *conn); /* * Try to parse the incoming data as an HTTP request. */ http_parse_error http_loop_parse_request(event_loop_conn *conn); /* * Try to match the parsed request with one of the defined routes, aka route the * request. */ void http_loop_route_request(event_loop_conn *conn); /* * Advance the processing of the routed request's processing by cycling through * the request's various steps. */ 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 * buffer will be free'd after the request has finished. */ void http_loop_res_set_body_buf(http_loop_ctx *ctx, const char *body, size_t body_len, bool owned); void http_loop_res_set_body_file(http_loop_ctx *ctx, const char *filename); void http_loop_res_add_header(http_loop_ctx *ctx, http_header type, const char *value, bool owned); /* * Request step that consumes the request body and stores it in a buffer */ bool http_loop_step_body_to_buf(event_loop_conn *conn); /* * Authenticate the request using the X-Api-Key header */ bool http_loop_step_auth(event_loop_conn *conn); /** * Initialize a new http loop */ event_loop *http_loop_init(http_loop_gctx *gctx); void http_loop_run(event_loop *el, int port); #endif