diff --git a/include/http.h b/include/http.h index 474dfbe..d9b9676 100644 --- a/include/http.h +++ b/include/http.h @@ -132,7 +132,7 @@ typedef enum http_response_body_type { } http_response_body_type; typedef struct http_response { - http_response_type type; + http_response_type status; const char *head; size_t head_len; size_t head_written; diff --git a/include/lander.h b/include/lander.h new file mode 100644 index 0000000..c990cef --- /dev/null +++ b/include/lander.h @@ -0,0 +1,8 @@ +#ifndef LANDER +#define LANDER + +#include "http_loop.h" + +extern http_route lander_routes[2]; + +#endif diff --git a/include/trie.h b/include/trie.h index 37d5341..912e438 100644 --- a/include/trie.h +++ b/include/trie.h @@ -19,9 +19,9 @@ #include #include -const static char charset[] = +static const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; -const static size_t charset_len = sizeof(charset) - 1; +static const size_t charset_len = sizeof(charset) - 1; // Length of randomly generated keys #define RANDOM_KEY_LENGTH_SHORT 4 diff --git a/src/http_loop/http_loop.c b/src/http_loop/http_loop.c index ba1131c..51ad32b 100644 --- a/src/http_loop/http_loop.c +++ b/src/http_loop/http_loop.c @@ -30,7 +30,7 @@ bool http_loop_handle_request(event_loop_conn *conn) { // 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; + ctx->res.status = http_method_not_implemented; conn->state = event_loop_conn_state_res; } else { http_loop_route_request(conn); diff --git a/src/http_loop/http_loop_ctx.c b/src/http_loop/http_loop_ctx.c index 1573c35..7029654 100644 --- a/src/http_loop/http_loop_ctx.c +++ b/src/http_loop/http_loop_ctx.c @@ -49,7 +49,7 @@ void http_loop_ctx_reset(http_loop_ctx *ctx) { ctx->res.header_count = 0; - ctx->res.type = 0; + ctx->res.status = 0; ctx->res.head_len = 0; ctx->res.head_written = 0; ctx->res.body_len = 0; diff --git a/src/http_loop/http_loop_req.c b/src/http_loop/http_loop_req.c index a09adeb..5712197 100644 --- a/src/http_loop/http_loop_req.c +++ b/src/http_loop/http_loop_req.c @@ -92,7 +92,6 @@ void http_loop_route_request(event_loop_conn *conn) { http_route *route; bool path_matched = false; - char c; for (size_t i = 0; i < gctx->route_count; i++) { route = &gctx->routes[i]; @@ -123,7 +122,7 @@ void http_loop_route_request(event_loop_conn *conn) { } // Fallthrough case - ctx->res.type = path_matched ? http_method_not_allowed : http_not_found; + ctx->res.status = path_matched ? http_method_not_allowed : http_not_found; conn->state = event_loop_conn_state_res; } diff --git a/src/http_loop/http_loop_res.c b/src/http_loop/http_loop_res.c index 0305f6f..196f653 100644 --- a/src/http_loop/http_loop_res.c +++ b/src/http_loop/http_loop_res.c @@ -1,6 +1,3 @@ -#include -#include - #include "http_loop.h" #include "log.h" @@ -17,15 +14,15 @@ static const char *http_response_format = "HTTP/1.1 %i %s\n" * written. */ void http_loop_init_header(http_response *res) { - if (res->type == 0) { - res->type = http_ok; + if (res->status == 0) { + res->status = http_ok; } const char *response_type_name = - http_response_type_names[res->type / 100 - 1][res->type % 100]; + http_response_type_names[res->status / 100 - 1][res->status % 100]; // First we calculate the size of the start of the header - int buf_size = snprintf(NULL, 0, http_response_format, res->type, + int buf_size = snprintf(NULL, 0, http_response_format, res->status, response_type_name, res->body_len); // We add each header's required size @@ -38,7 +35,7 @@ void http_loop_init_header(http_response *res) { // The + 1 is required to store the final null byte, but we will replace it // with the required final newline char *buf = malloc(buf_size + 1); - buf_size = sprintf(buf, http_response_format, res->type, response_type_name, + buf_size = sprintf(buf, http_response_format, res->status, response_type_name, res->body_len); for (size_t i = 0; i < res->header_count; i++) { @@ -87,8 +84,8 @@ void http_loop_write_response(event_loop_conn *conn) { switch (res->body_type) { case http_response_body_buf: - memcpy(&conn->wbuf[conn->wbuf_size], &res->body[res->body_written], - bytes_to_write); + memcpy(&conn->wbuf[conn->wbuf_size], + &((const char *)res->body)[res->body_written], bytes_to_write); conn->wbuf_size += bytes_to_write; res->body_written += bytes_to_write; break; @@ -101,32 +98,3 @@ void http_loop_write_response(event_loop_conn *conn) { } } } - -void http_loop_res_set_body_buf(http_loop_ctx *ctx, const char *body, - size_t body_len, bool owned) { - ctx->res.body_type = http_response_body_buf; - ctx->res.body = (void *)body; - ctx->res.body_len = body_len; - ctx->res.owns_body = owned; -} - -void http_loop_res_set_body_file(http_loop_ctx *ctx, const char *filename) { - struct stat st; - stat(filename, &st); - - // TODO error handling - FILE *f = fopen(filename, "r"); - - ctx->res.body_type = http_response_body_file; - ctx->res.body = f; - ctx->res.body_len = st.st_size; -} - -void http_loop_res_add_header(http_loop_ctx *ctx, http_header type, - const char *value, bool owned) { - ctx->res.headers[ctx->res.header_count].type = type; - ctx->res.headers[ctx->res.header_count].value = value; - ctx->res.headers[ctx->res.header_count].owned = owned; - - ctx->res.header_count++; -} diff --git a/src/http_loop/http_loop_tools.c b/src/http_loop/http_loop_tools.c new file mode 100644 index 0000000..565f6d3 --- /dev/null +++ b/src/http_loop/http_loop_tools.c @@ -0,0 +1,33 @@ +#include +#include + +#include "http_loop.h" + +void http_loop_res_set_body_buf(http_loop_ctx *ctx, const char *body, + size_t body_len, bool owned) { + ctx->res.body_type = http_response_body_buf; + ctx->res.body = (void *)body; + ctx->res.body_len = body_len; + ctx->res.owns_body = owned; +} + +void http_loop_res_set_body_file(http_loop_ctx *ctx, const char *filename) { + struct stat st; + stat(filename, &st); + + // TODO error handling + FILE *f = fopen(filename, "r"); + + ctx->res.body_type = http_response_body_file; + ctx->res.body = f; + ctx->res.body_len = st.st_size; +} + +void http_loop_res_add_header(http_loop_ctx *ctx, http_header type, + const char *value, bool owned) { + ctx->res.headers[ctx->res.header_count].type = type; + ctx->res.headers[ctx->res.header_count].value = value; + ctx->res.headers[ctx->res.header_count].owned = owned; + + ctx->res.header_count++; +} diff --git a/src/lander/lander.c b/src/lander/lander.c new file mode 100644 index 0000000..422651d --- /dev/null +++ b/src/lander/lander.c @@ -0,0 +1,57 @@ +#include + +#include "lander.h" + +static const char index_page[] = + "\n" + "\n" + " \n" + "

r8r.be

\n" + "

This is the URL shortener and pastebin accompanying my site, The Rusty Bever.

\n" + " \n" + "\n"; + +bool lander_get_index(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + + http_loop_res_set_body_buf(ctx, index_page, sizeof(index_page) - 1, false); + + conn->state = event_loop_conn_state_res; + return true; +} + +bool lander_get_entry(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + + const char *key = &ctx->req.path[ctx->req.regex_groups[1].rm_so]; + int key_len = ctx->req.regex_groups[1].rm_eo - ctx->req.regex_groups[1].rm_so; + + Entry *entry; + TrieExitCode res = trie_search_len(ctx->g->trie, &entry, key, key_len); + + if (res == NotFound) { + ctx->res.status = http_not_found; + } else if (entry->type == Redirect) { + ctx->res.status = http_moved_permanently; + http_loop_res_add_header(ctx, http_header_location, entry->string, false); + } else if (entry->type == Paste) { + char fname[8 + key_len]; + sprintf(fname, "pastes/%.*s", key_len, key); + + http_loop_res_set_body_file(ctx, fname); + } + + conn->state = event_loop_conn_state_res; + + return true; +} + +http_route lander_routes[] = {{.type = http_route_literal, + .method = http_get, + .path = "/", + .steps = {lander_get_index, NULL}}, + {.type = http_route_regex, + .method = http_get, + .path = "^/\\([^/]\\+\\)$", + .steps = {lander_get_entry, NULL}}}; diff --git a/src/lander/lander_get.c b/src/lander/lander_get.c new file mode 100644 index 0000000..e69de29 diff --git a/src/main.c b/src/main.c index c072b2c..217f83e 100644 --- a/src/main.c +++ b/src/main.c @@ -1,65 +1,8 @@ #include -#include "http.h" -#include "http_loop.h" +#include "lander.h" #include "log.h" -const char index_page[] = - "\n" - "\n" - " \n" - "

r8r.be

\n" - "

This is the URL shortener and pastebin accompanying my site, The Rusty Bever.

\n" - " \n" - "\n"; - -bool lander_get_index(event_loop_conn *conn) { - http_loop_ctx *ctx = conn->ctx; - - http_loop_res_set_body_file(ctx, "Dockerfile"); - - conn->state = event_loop_conn_state_res; - - return true; -} - -bool lander_get_entry(event_loop_conn *conn) { - http_loop_ctx *ctx = conn->ctx; - - const char *key = &ctx->req.path[ctx->req.regex_groups[1].rm_so]; - int key_len = - ctx->req.regex_groups[1].rm_eo - ctx->req.regex_groups[1].rm_so; - - Entry *entry; - TrieExitCode res = trie_search_len(ctx->g->trie, &entry, key, key_len); - - if (res == NotFound) { - ctx->res.type = http_not_found; - } else if (entry->type == Redirect) { - ctx->res.type = http_moved_permanently; - http_loop_res_add_header(ctx, http_header_location, entry->string, false); - } else if (entry->type == Paste) { - char fname[8 + key_len]; - sprintf(fname, "pastes/%.*s", key_len, key); - - http_loop_res_set_body_file(ctx, fname); - } - - conn->state = event_loop_conn_state_res; - - return true; -} - -http_route routes[] = {{.type = http_route_literal, - .method = http_get, - .path = "/", - .steps = {lander_get_index, NULL}}, - {.type = http_route_regex, - .method = http_get, - .path = "^/\\([^/]\\+\\)$", - .steps = {lander_get_entry, NULL}}}; - int main() { setvbuf(stdout, NULL, _IONBF, 0); @@ -76,8 +19,8 @@ int main() { http_loop_gctx *gctx = http_loop_gctx_init(); gctx->trie = trie; - gctx->routes = routes; - gctx->route_count = sizeof(routes) / sizeof(routes[0]); + gctx->routes = lander_routes; + gctx->route_count = sizeof(lander_routes) / sizeof(lander_routes[0]); event_loop *el = http_loop_init(gctx); http_loop_run(el, 8000);