feat(lander): introduce file entry type

lsm
Jef Roosens 2023-11-12 13:57:11 +01:00
parent 3d48ee8019
commit 7fac278ead
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
5 changed files with 93 additions and 33 deletions

View File

@ -4,7 +4,7 @@
#include "http_loop.h" #include "http_loop.h"
#include "lsm/store.h" #include "lsm/store.h"
extern http_route lander_routes[5]; extern http_route lander_routes[6];
typedef struct lander_gctx { typedef struct lander_gctx {
const char *data_dir; const char *data_dir;
@ -27,6 +27,7 @@ typedef enum lander_attr_type : uint8_t {
typedef enum lander_entry_type : uint8_t { typedef enum lander_entry_type : uint8_t {
lander_entry_type_redirect = 0, lander_entry_type_redirect = 0,
lander_entry_type_paste = 1, lander_entry_type_paste = 1,
lander_entry_type_file = 2,
} lander_entry_type; } lander_entry_type;
void *lander_gctx_init(); 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_remove_entry(event_loop_conn *conn);
bool lander_post_file_lsm(event_loop_conn *conn);
#endif #endif

View File

@ -38,4 +38,12 @@ elif [ "$1" = pl ]; then
-H "X-Api-Key: $API_KEY" \ -H "X-Api-Key: $API_KEY" \
--data-binary @"$2" \ --data-binary @"$2" \
"$URL/pl/$3" "$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 fi

View File

@ -44,6 +44,13 @@ http_route lander_routes[] = {
lander_post_paste_lsm, lander_stream_body_to_entry, NULL}, lander_post_paste_lsm, lander_stream_body_to_entry, NULL},
.steps_res = {http_loop_step_write_header, http_loop_step_write_body, .steps_res = {http_loop_step_write_header, http_loop_step_write_body,
NULL}}, 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)); } void *lander_gctx_init() { return calloc(1, sizeof(lander_gctx)); }

View File

@ -26,6 +26,55 @@ bool lander_get_index(event_loop_conn *conn) {
return true; 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) { bool lander_get_entry_lsm(event_loop_conn *conn) {
http_loop_ctx *ctx = conn->ctx; http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c; 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, lsm_entry_attr_get_uint8_t((uint8_t *)&t, c_ctx->entry,
lander_attr_type_entry_type); lander_attr_type_entry_type);
if (t == lander_entry_type_redirect) { switch (t) {
// For redirects, the URL is stored as an in-memory attribute case lander_entry_type_redirect:
lsm_str *url_attr_val; lander_get_redirect(conn);
break;
// This shouldn't be able to happen case lander_entry_type_paste:
if (lsm_entry_attr_get(&url_attr_val, c_ctx->entry, lander_attr_type_url) != lander_get_paste(conn);
lsm_error_ok) { break;
error("Entry of type redirect detected without URL attribute"); case lander_entry_type_file:
lander_get_file(conn);
ctx->res.status = http_internal_server_error; break;
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);
} }
return true; return true;

View File

@ -164,6 +164,21 @@ bool lander_post_paste_lsm(event_loop_conn *conn) {
return true; 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) { bool lander_stream_body_to_entry(event_loop_conn *conn) {
http_loop_ctx *ctx = conn->ctx; http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c; lander_ctx *c_ctx = ctx->c;