lander/src/lander/lander_get.c

148 lines
4.2 KiB
C

#include <stdio.h>
#include <string.h>
#include "lnm/http/consts.h"
#include "lnm/http/loop.h"
#include "lnm/http/req.h"
#include "lnm/log.h"
#include "lnm/loop.h"
#include "lsm/store.h"
#include "lander.h"
static const char index_page[] =
"<!DOCTYPE html>\n"
"<html>\n"
" <body>\n"
" <h1>r8r.be</h1>\n"
" <p>This is the URL shortener and pastebin accompanying my site, <a "
"href=\"https://rustybever.be\">The Rusty Bever</a>.</p>\n"
" </body>\n"
"</html>\n";
lnm_http_step_err lander_get_index(lnm_http_conn *conn) {
lnm_http_loop_ctx *ctx = conn->ctx;
lnm_http_res_body_set_buf(&ctx->res, (char *)index_page,
sizeof(index_page) - 1, false);
lnm_http_res_add_header(&ctx->res, lnm_http_header_content_type, "text/html",
false);
return lnm_http_step_err_done;
}
lnm_http_step_err lander_get_redirect(lnm_http_conn *conn) {
lnm_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) {
lnm_lerror("lander", "%s",
"Entry of type redirect detected without URL attribute");
ctx->res.status = lnm_http_status_internal_server_error;
lsm_entry_close(c_ctx->entry);
c_ctx->entry = NULL;
return lnm_http_step_err_res;
}
lnm_http_res_add_header_len(&ctx->res, lnm_http_header_location,
(char *)lsm_str_ptr(url_attr_val),
lsm_str_len(url_attr_val), false);
ctx->res.status = lnm_http_status_moved_permanently;
return lnm_http_step_err_done;
}
lnm_err lander_entry_data_streamer(uint64_t *written, char *buf,
lnm_http_conn *conn, uint64_t offset,
uint64_t len) {
// TODO respect offset variable
lnm_http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;
lsm_entry_data_read(written, buf, c_ctx->entry, len);
return lnm_err_ok;
}
lnm_http_step_err lander_get_paste(lnm_http_conn *conn) {
lnm_http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;
lnm_http_res_body_set_fn(&ctx->res, lander_entry_data_streamer,
lsm_entry_data_len(c_ctx->entry));
lnm_http_res_add_header(&ctx->res, lnm_http_header_content_type, "text/plain",
false);
return lnm_http_step_err_done;
}
lnm_http_step_err lander_get_file(lnm_http_conn *conn) {
lnm_http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;
lnm_http_res_body_set_fn(&ctx->res, lander_entry_data_streamer,
lsm_entry_data_len(c_ctx->entry));
lander_attr_to_header(ctx, lander_attr_type_content_type,
lnm_http_header_content_type);
return lnm_http_step_err_done;
}
lnm_http_step_err lander_get_entry(lnm_http_conn *conn) {
lnm_http_loop_ctx *ctx = conn->ctx;
lander_ctx *c_ctx = ctx->c;
lnm_http_loop_gctx *gctx = ctx->g;
lander_gctx *c_gctx = gctx->c;
const char *key_s;
size_t key_len = lnm_http_req_route_segment(&key_s, &ctx->req, "key");
lsm_str *key;
lsm_str_init_copy_n(&key, (char *)key_s, key_len);
lsm_error lsm_res = lsm_store_open_read(&c_ctx->entry, c_gctx->store, key);
lsm_str_free(key);
switch (lsm_res) {
case lsm_error_ok:
break;
case lsm_error_not_found:
ctx->res.status = lnm_http_status_not_found;
return lnm_http_step_err_res;
default:
ctx->res.status = lnm_http_status_internal_server_error;
return lnm_http_step_err_res;
}
lander_entry_type t;
lsm_entry_attr_get_uint8_t((uint8_t *)&t, c_ctx->entry,
lander_attr_type_entry_type);
lnm_http_step_err res;
switch (t) {
case lander_entry_type_redirect:
res = lander_get_redirect(conn);
break;
case lander_entry_type_paste:
res = lander_get_paste(conn);
break;
case lander_entry_type_file:
res = lander_get_file(conn);
break;
default:
ctx->res.status = lnm_http_status_internal_server_error;
res = lnm_http_step_err_res;
}
return res;
}