feat: fully support redirect & paste routes
ci/woodpecker/pr/woodpecker Pipeline failed Details

c-web-server
Jef Roosens 2023-05-30 21:38:22 +02:00
parent 58e2d8a02e
commit a6257a923d
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
2 changed files with 70 additions and 70 deletions

View File

@ -16,9 +16,9 @@ http_route lander_routes[] = {
.path = "^/s\\(l\\?\\)/\\([^/]*\\)$", .path = "^/s\\(l\\?\\)/\\([^/]*\\)$",
.steps = {http_loop_step_auth, http_loop_step_body_to_buf, .steps = {http_loop_step_auth, http_loop_step_body_to_buf,
lander_post_redirect, NULL}}, lander_post_redirect, NULL}},
{.type = http_route_literal, {.type = http_route_regex,
.method = http_post, .method = http_post,
.path = "/p/", .path = "^/p\\(l\\?\\)/\\([^/]*\\)$",
.steps = {http_loop_step_auth, lander_post_paste, .steps = {http_loop_step_auth, lander_post_paste,
http_loop_step_body_to_file, http_loop_step_switch_res, NULL}}, http_loop_step_body_to_file, http_loop_step_switch_res, NULL}},
}; };

View File

@ -2,12 +2,63 @@
#include "lander.h" #include "lander.h"
#include "log.h" #include "log.h"
bool lander_post_redirect(event_loop_conn *conn) { // TODO entry leaks if key is already present
http_loop_ctx *ctx = conn->ctx; static bool add_entry(char **key_ptr, int *key_len_ptr, http_loop_ctx *ctx,
Entry *entry, bool random) {
// The first match group matches the "long" path // The first match group matches the "long" path
bool secure = bool secure =
(ctx->req.regex_groups[1].rm_eo - ctx->req.regex_groups[1].rm_so) == 1; (ctx->req.regex_groups[1].rm_eo - ctx->req.regex_groups[1].rm_so) == 1;
char *key;
int key_len = 0;
TrieExitCode res;
if (random) {
res = trie_add_random(ctx->g->trie, &key, entry, secure);
if (res == Ok) {
key_len = strlen(key);
}
} else {
key = (char *)&ctx->req.path[ctx->req.regex_groups[2].rm_so];
key_len = ctx->req.regex_groups[2].rm_eo - ctx->req.regex_groups[2].rm_so;
res = trie_add_len(ctx->g->trie, key, key_len, entry);
}
switch (res) {
case Ok:
break;
case AlreadyPresent:
ctx->res.status = http_conflict;
return false;
default:
ctx->res.status = http_internal_server_error;
return false;
}
// Add a slash to the key and add it as the location header
char *buf = malloc(key_len + 2);
memcpy(&buf[1], key, key_len);
buf[0] = '/';
buf[key_len + 1] = '\0';
http_res_add_header(&ctx->res, http_header_location, buf, true);
if (key_ptr != NULL) {
*key_ptr = key;
}
if (key_len_ptr != NULL) {
*key_len_ptr = key_len;
}
return true;
}
bool lander_post_redirect(event_loop_conn *conn) {
http_loop_ctx *ctx = conn->ctx;
bool random = bool random =
ctx->req.regex_groups[2].rm_eo == ctx->req.regex_groups[2].rm_so; ctx->req.regex_groups[2].rm_eo == ctx->req.regex_groups[2].rm_so;
@ -18,60 +69,18 @@ bool lander_post_redirect(event_loop_conn *conn) {
Entry *new_entry = entry_new(Redirect, url); Entry *new_entry = entry_new(Redirect, url);
// The entry duplicates the string
free(url);
// We don't check the result here, because we would perform the same action
// either way
char *key; char *key;
int key_len; add_entry(&key, NULL, ctx, new_entry, random);
if (random) {
TrieExitCode res = trie_add_random(ctx->g->trie, &key, new_entry, secure);
if (res != Ok) {
error("trie_add_random failed with exit code %i", res);
ctx->res.status = http_internal_server_error;
conn->state = event_loop_conn_state_res;
return true;
}
key_len = strlen(key);
} else {
key = (char *)&ctx->req.path[ctx->req.regex_groups[2].rm_so];
key_len = ctx->req.regex_groups[2].rm_eo - ctx->req.regex_groups[2].rm_so;
TrieExitCode res = trie_add_len(ctx->g->trie, key, key_len, new_entry);
switch (res) {
case Ok:
break;
case AlreadyPresent:
ctx->res.status = http_conflict;
break;
default:
ctx->res.status = http_internal_server_error;
}
if (res != Ok) {
error("trie_add_len failed with exit code %i", res);
conn->state = event_loop_conn_state_res;
return true;
}
}
// Add a slash to the key and add it as the location header
char *buf = malloc(key_len + 2);
memcpy(&buf[1], key, key_len);
buf[0] = '/';
buf[key_len + 1] = '\0';
if (random) { if (random) {
free(key); free(key);
} }
http_res_add_header(&ctx->res, http_header_location, buf, true);
conn->state = event_loop_conn_state_res; conn->state = event_loop_conn_state_res;
return true; return true;
@ -79,37 +88,28 @@ bool lander_post_redirect(event_loop_conn *conn) {
bool lander_post_paste(event_loop_conn *conn) { bool lander_post_paste(event_loop_conn *conn) {
http_loop_ctx *ctx = conn->ctx; http_loop_ctx *ctx = conn->ctx;
bool random =
ctx->req.regex_groups[2].rm_eo == ctx->req.regex_groups[2].rm_so;
char *key; char *key;
int key_len;
Entry *new_entry = entry_new(Paste, ""); Entry *new_entry = entry_new(Paste, "");
TrieExitCode res = trie_add_random(ctx->g->trie, &key, new_entry, false);
if (res != Ok) { if (!add_entry(&key, &key_len, ctx, new_entry, random)) {
error("trie_add_random failed with exit code %i", res);
ctx->res.status = http_internal_server_error;
conn->state = event_loop_conn_state_res; conn->state = event_loop_conn_state_res;
return true; return true;
} }
// Add a slash to the key and add it as the location header
size_t key_len = strlen(key);
char *buf = malloc(key_len + 2);
memcpy(&buf[1], key, key_len);
buf[0] = '/';
buf[key_len + 1] = '\0';
http_res_add_header(&ctx->res, http_header_location, buf, true);
// TODO free this // TODO free this
char *fname = malloc(8 + key_len); char *fname = malloc(8 + key_len);
sprintf(fname, "pastes/%s", key); sprintf(fname, "pastes/%.*s", key_len, key);
ctx->req.body_file_name = fname; ctx->req.body_file_name = fname;
if (random) {
free(key); free(key);
}
return true; return true;
} }