148 lines
4.2 KiB
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;
|
|
}
|