From 7fac278eada77bb49930ce5d62aacd0c2afdecdf Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 12 Nov 2023 13:57:11 +0100 Subject: [PATCH 1/2] feat(lander): introduce file entry type --- include/lander.h | 5 ++- landerctl | 8 ++++ src/lander/lander.c | 7 ++++ src/lander/lander_get.c | 91 ++++++++++++++++++++++++++-------------- src/lander/lander_post.c | 15 +++++++ 5 files changed, 93 insertions(+), 33 deletions(-) diff --git a/include/lander.h b/include/lander.h index 61c4297..2d8f8e5 100644 --- a/include/lander.h +++ b/include/lander.h @@ -4,7 +4,7 @@ #include "http_loop.h" #include "lsm/store.h" -extern http_route lander_routes[5]; +extern http_route lander_routes[6]; typedef struct lander_gctx { const char *data_dir; @@ -27,6 +27,7 @@ typedef enum lander_attr_type : uint8_t { typedef enum lander_entry_type : uint8_t { lander_entry_type_redirect = 0, lander_entry_type_paste = 1, + lander_entry_type_file = 2, } lander_entry_type; void *lander_gctx_init(); @@ -59,4 +60,6 @@ bool lander_post_redirect_body_to_attr(event_loop_conn *conn); bool lander_remove_entry(event_loop_conn *conn); +bool lander_post_file_lsm(event_loop_conn *conn); + #endif diff --git a/landerctl b/landerctl index c0433a5..f7bdded 100755 --- a/landerctl +++ b/landerctl @@ -38,4 +38,12 @@ elif [ "$1" = pl ]; then -H "X-Api-Key: $API_KEY" \ --data-binary @"$2" \ "$URL/pl/$3" + +elif [ "$1" = f ]; then + curl \ + -w "${URL}%header{location}" \ + -XPOST \ + -H "X-Api-Key: $API_KEY" \ + --data-binary @"$2" \ + "$URL/f/$3" fi diff --git a/src/lander/lander.c b/src/lander/lander.c index a045428..ba34ea1 100644 --- a/src/lander/lander.c +++ b/src/lander/lander.c @@ -44,6 +44,13 @@ http_route lander_routes[] = { lander_post_paste_lsm, lander_stream_body_to_entry, NULL}, .steps_res = {http_loop_step_write_header, http_loop_step_write_body, NULL}}, + {.type = http_route_regex, + .method = http_post, + .path = "^/f(l?)/([^/]*)$", + .steps = {http_loop_step_auth, http_loop_step_parse_content_length, + lander_post_file_lsm, lander_stream_body_to_entry, NULL}, + .steps_res = {http_loop_step_write_header, http_loop_step_write_body, + NULL}}, }; void *lander_gctx_init() { return calloc(1, sizeof(lander_gctx)); } diff --git a/src/lander/lander_get.c b/src/lander/lander_get.c index 7c467b5..03076c8 100644 --- a/src/lander/lander_get.c +++ b/src/lander/lander_get.c @@ -26,6 +26,55 @@ bool lander_get_index(event_loop_conn *conn) { return true; } +void lander_get_redirect(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + lander_ctx *c_ctx = ctx->c; + + // For redirects, the URL is stored as an in-memory attribute + lsm_str *url_attr_val; + + // This shouldn't be able to happen + if (lsm_entry_attr_get(&url_attr_val, c_ctx->entry, lander_attr_type_url) != + lsm_error_ok) { + error("Entry of type redirect detected without URL attribute"); + + ctx->res.status = http_internal_server_error; + lsm_entry_close(c_ctx->entry); + c_ctx->entry = NULL; + + return; + } + + char *buf = malloc(lsm_str_len(url_attr_val) + 1); + memcpy(buf, lsm_str_ptr(url_attr_val), lsm_str_len(url_attr_val)); + + buf[lsm_str_len(url_attr_val)] = '\0'; + + ctx->res.status = http_moved_permanently; + http_res_add_header(&ctx->res, http_header_location, buf, true); + + // We no longer need the entry at this point, so we can unlock it early + // This will also signal to the response code not to read any data from + // the entry + lsm_entry_close(c_ctx->entry); + c_ctx->entry = NULL; +} + +void lander_get_paste(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + lander_ctx *c_ctx = ctx->c; + + ctx->res.body.expected_len = lsm_entry_data_len(c_ctx->entry); + http_res_set_mime_type(&ctx->res, http_mime_txt); +} + +void lander_get_file(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + lander_ctx *c_ctx = ctx->c; + + ctx->res.body.expected_len = lsm_entry_data_len(c_ctx->entry); +} + bool lander_get_entry_lsm(event_loop_conn *conn) { http_loop_ctx *ctx = conn->ctx; lander_ctx *c_ctx = ctx->c; @@ -53,38 +102,16 @@ bool lander_get_entry_lsm(event_loop_conn *conn) { lsm_entry_attr_get_uint8_t((uint8_t *)&t, c_ctx->entry, lander_attr_type_entry_type); - if (t == lander_entry_type_redirect) { - // For redirects, the URL is stored as an in-memory attribute - lsm_str *url_attr_val; - - // This shouldn't be able to happen - if (lsm_entry_attr_get(&url_attr_val, c_ctx->entry, lander_attr_type_url) != - lsm_error_ok) { - error("Entry of type redirect detected without URL attribute"); - - ctx->res.status = http_internal_server_error; - lsm_entry_close(c_ctx->entry); - c_ctx->entry = NULL; - - return true; - } - - char *buf = malloc(lsm_str_len(url_attr_val) + 1); - memcpy(buf, lsm_str_ptr(url_attr_val), lsm_str_len(url_attr_val)); - - buf[lsm_str_len(url_attr_val)] = '\0'; - - ctx->res.status = http_moved_permanently; - http_res_add_header(&ctx->res, http_header_location, buf, true); - - // We no longer need the entry at this point, so we can unlock it early - // This will also signal to the response code not to read any data from - // the entry - lsm_entry_close(c_ctx->entry); - c_ctx->entry = NULL; - } else { - ctx->res.body.expected_len = lsm_entry_data_len(c_ctx->entry); - http_res_set_mime_type(&ctx->res, http_mime_txt); + switch (t) { + case lander_entry_type_redirect: + lander_get_redirect(conn); + break; + case lander_entry_type_paste: + lander_get_paste(conn); + break; + case lander_entry_type_file: + lander_get_file(conn); + break; } return true; diff --git a/src/lander/lander_post.c b/src/lander/lander_post.c index 429ea39..13679cc 100644 --- a/src/lander/lander_post.c +++ b/src/lander/lander_post.c @@ -164,6 +164,21 @@ bool lander_post_paste_lsm(event_loop_conn *conn) { return true; } +bool lander_post_file_lsm(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + lander_ctx *c_ctx = ctx->c; + + if (!lander_insert_entry(ctx)) { + conn->state = event_loop_conn_state_res; + return true; + } + + lsm_entry_attr_insert_uint8_t(c_ctx->entry, lander_attr_type_entry_type, + lander_entry_type_file); + + return true; +} + bool lander_stream_body_to_entry(event_loop_conn *conn) { http_loop_ctx *ctx = conn->ctx; lander_ctx *c_ctx = ctx->c; From 70f622d9f3329f565a7b229ab992c8c52265883f Mon Sep 17 00:00:00 2001 From: Chewing_Bever Date: Sun, 12 Nov 2023 14:12:13 +0100 Subject: [PATCH 2/2] feat(lander): support sendind extra attributes as custom headers --- include/lander.h | 6 ++++++ src/lander/lander.c | 36 +++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/include/lander.h b/include/lander.h index 2d8f8e5..1bb38d3 100644 --- a/include/lander.h +++ b/include/lander.h @@ -62,4 +62,10 @@ bool lander_remove_entry(event_loop_conn *conn); bool lander_post_file_lsm(event_loop_conn *conn); +/** + * Parse any custom headers and add them as attributes to the context's LSM + * entry + */ +bool lander_headers_to_attrs(event_loop_conn *conn); + #endif diff --git a/src/lander/lander.c b/src/lander/lander.c index ba34ea1..79518b0 100644 --- a/src/lander/lander.c +++ b/src/lander/lander.c @@ -48,11 +48,19 @@ http_route lander_routes[] = { .method = http_post, .path = "^/f(l?)/([^/]*)$", .steps = {http_loop_step_auth, http_loop_step_parse_content_length, - lander_post_file_lsm, lander_stream_body_to_entry, NULL}, + lander_post_file_lsm, lander_headers_to_attrs, lander_stream_body_to_entry, NULL}, .steps_res = {http_loop_step_write_header, http_loop_step_write_body, NULL}}, }; +struct { + char *header; + lander_attr_type attr_type; +} header_to_attr_type[] = { + { "X-Lander-Content-Type", lander_attr_type_content_type }, + { NULL, 0 }, +}; + void *lander_gctx_init() { return calloc(1, sizeof(lander_gctx)); } void *lander_ctx_init() { return calloc(1, sizeof(lander_ctx)); } @@ -68,3 +76,29 @@ void lander_ctx_reset(lander_ctx *ctx) { } void lander_ctx_free(lander_ctx *ctx) { free(ctx); } + +bool lander_headers_to_attrs(event_loop_conn *conn) { + http_loop_ctx *ctx = conn->ctx; + lander_ctx *c_ctx = ctx->c; + + for (size_t i = 0; i < ctx->req.num_headers; i++) { + struct phr_header *header = &ctx->req.headers[i]; + + int j = 0; + + while (header_to_attr_type[j].header != NULL) { + if (strncmp(header->name, header_to_attr_type[j].header, header->name_len) == 0) { + lsm_str *value; + lsm_str_init_copy_n(&value, (char *)header->value, header->value_len); + + lsm_entry_attr_insert(c_ctx->entry, header_to_attr_type[j].attr_type, value); + + break; + } + + j++; + } + } + + return true; +}