feat: add long & custom redirect urls
parent
f07042e798
commit
58e2d8a02e
|
@ -9,6 +9,8 @@
|
|||
#include "http/types.h"
|
||||
#include "trie.h"
|
||||
|
||||
#define HTTP_LOOP_MAX_STEPS 17
|
||||
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
|
||||
|
||||
|
@ -22,7 +24,7 @@ typedef struct http_route {
|
|||
http_method method;
|
||||
char *path;
|
||||
regex_t *regex;
|
||||
bool (*steps[5])(event_loop_conn *);
|
||||
bool (*steps[HTTP_LOOP_MAX_STEPS])(event_loop_conn *);
|
||||
} http_route;
|
||||
|
||||
/*
|
||||
|
|
|
@ -88,6 +88,9 @@ TrieExitCode trie_search_len(Trie *trie, Entry **entry_ptr, const char *key,
|
|||
*/
|
||||
TrieExitCode trie_add(Trie *trie, const char *key, Entry *entry);
|
||||
|
||||
TrieExitCode trie_add_len(Trie *trie, const char *key, size_t key_len,
|
||||
Entry *entry);
|
||||
|
||||
/**
|
||||
* Add an entry by generating a random string as the key.
|
||||
*
|
||||
|
|
|
@ -11,9 +11,9 @@ http_route lander_routes[] = {
|
|||
.method = http_get,
|
||||
.path = "^/\\([^/]\\+\\)$",
|
||||
.steps = {lander_get_entry, NULL}},
|
||||
{.type = http_route_literal,
|
||||
{.type = http_route_regex,
|
||||
.method = http_post,
|
||||
.path = "/s/",
|
||||
.path = "^/s\\(l\\?\\)/\\([^/]*\\)$",
|
||||
.steps = {http_loop_step_auth, http_loop_step_body_to_buf,
|
||||
lander_post_redirect, NULL}},
|
||||
{.type = http_route_literal,
|
||||
|
|
|
@ -41,6 +41,8 @@ bool lander_get_entry(event_loop_conn *conn) {
|
|||
sprintf(fname, "pastes/%.*s", key_len, key);
|
||||
|
||||
http_res_set_body_file(&ctx->res, fname);
|
||||
// TODO don't call everything a text file
|
||||
http_res_set_mime_type(&ctx->res, http_mime_txt);
|
||||
}
|
||||
|
||||
conn->state = event_loop_conn_state_res;
|
||||
|
|
|
@ -5,14 +5,24 @@
|
|||
bool lander_post_redirect(event_loop_conn *conn) {
|
||||
http_loop_ctx *ctx = conn->ctx;
|
||||
|
||||
// The first match group matches the "long" path
|
||||
bool secure =
|
||||
(ctx->req.regex_groups[1].rm_eo - ctx->req.regex_groups[1].rm_so) == 1;
|
||||
bool random =
|
||||
ctx->req.regex_groups[2].rm_eo == ctx->req.regex_groups[2].rm_so;
|
||||
|
||||
// Allocate a new buffer to pass to the trie
|
||||
char *url = malloc(ctx->req.body_len + 1);
|
||||
memcpy(url, ctx->req.body.buf, ctx->req.body_len);
|
||||
url[ctx->req.body_len] = '\0';
|
||||
|
||||
char *key;
|
||||
Entry *new_entry = entry_new(Redirect, url);
|
||||
TrieExitCode res = trie_add_random(ctx->g->trie, &key, new_entry, false);
|
||||
|
||||
char *key;
|
||||
int key_len;
|
||||
|
||||
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);
|
||||
|
@ -23,15 +33,42 @@ bool lander_post_redirect(event_loop_conn *conn) {
|
|||
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
|
||||
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';
|
||||
|
||||
if (random) {
|
||||
free(key);
|
||||
}
|
||||
|
||||
http_res_add_header(&ctx->res, http_header_location, buf, true);
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ TrieExitCode trie_init(Trie **trie_ptr, const char *file_path) {
|
|||
char buffer[8192];
|
||||
EntryType type;
|
||||
Entry *entry;
|
||||
char *string;
|
||||
int i, j;
|
||||
TrieExitCode status;
|
||||
|
||||
|
@ -109,7 +108,6 @@ SearchResult trie_search_node_len(Trie *trie, const char *key, size_t key_len) {
|
|||
SearchResult out = {NULL, NULL};
|
||||
|
||||
size_t i = 0;
|
||||
size_t offset;
|
||||
TrieNode **node_ptr = &(trie->root);
|
||||
TrieNode **child_ptr;
|
||||
|
||||
|
@ -182,7 +180,8 @@ TrieExitCode trie_search(Trie *trie, Entry **entry_ptr, const char *key) {
|
|||
* @return true if the string wasn't present in the trie and thus added, false
|
||||
* otherwise
|
||||
*/
|
||||
TrieExitCode trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
|
||||
TrieExitCode trie_add_len_no_lock(Trie *trie, const char *key, size_t key_len,
|
||||
Entry *entry) {
|
||||
size_t i = 0;
|
||||
uint8_t offset;
|
||||
TrieNode **node_ptr = &(trie->root);
|
||||
|
@ -191,7 +190,7 @@ TrieExitCode trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
|
|||
|
||||
do {
|
||||
offset = 0;
|
||||
child_node_ptr = tnode_search(*node_ptr, string[i], true);
|
||||
child_node_ptr = tnode_search(*node_ptr, key[i], true);
|
||||
|
||||
i++;
|
||||
|
||||
|
@ -200,11 +199,11 @@ TrieExitCode trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
|
|||
if (*child_node_ptr == NULL) {
|
||||
child_node = tnode_init();
|
||||
|
||||
while (offset < TRIE_MAX_SKIP_SIZE && string[i + offset] != DELIMITER) {
|
||||
while (offset < TRIE_MAX_SKIP_SIZE && i + offset < key_len) {
|
||||
offset++;
|
||||
}
|
||||
|
||||
memcpy(child_node->string, string + i, offset);
|
||||
memcpy(child_node->string, key + i, offset);
|
||||
|
||||
child_node->string_len = offset;
|
||||
*child_node_ptr = child_node;
|
||||
|
@ -213,7 +212,7 @@ TrieExitCode trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
|
|||
// allowed skip length, we continue through the loop. The next iteration
|
||||
// will enter this if statement again, and perform the same loop, until
|
||||
// the string is fully added to the trie.
|
||||
if (string[i + offset] != DELIMITER) {
|
||||
if (i + offset < key_len) {
|
||||
node_ptr = child_node_ptr;
|
||||
i += offset;
|
||||
|
||||
|
@ -229,7 +228,7 @@ TrieExitCode trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
|
|||
|
||||
while (offset < (*child_node_ptr)->string_len) {
|
||||
// String no longer aligns with edge, so we have to split
|
||||
if (string[i + offset] != (*child_node_ptr)->string[offset]) {
|
||||
if (key[i + offset] != (*child_node_ptr)->string[offset]) {
|
||||
TrieNode *split_node = tnode_init();
|
||||
child_node = *child_node_ptr;
|
||||
|
||||
|
@ -272,7 +271,7 @@ TrieExitCode trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
|
|||
node_ptr = child_node_ptr;
|
||||
|
||||
i += offset;
|
||||
} while (string[i] != DELIMITER);
|
||||
} while (i < key_len);
|
||||
|
||||
if ((*child_node_ptr)->represents) {
|
||||
return AlreadyPresent;
|
||||
|
@ -284,12 +283,17 @@ TrieExitCode trie_add_no_lock(Trie *trie, const char *string, Entry *entry) {
|
|||
return Ok;
|
||||
}
|
||||
|
||||
TrieExitCode trie_add(Trie *trie, const char *key, Entry *entry) {
|
||||
TrieExitCode trie_add_no_lock(Trie *trie, const char *key, Entry *entry) {
|
||||
return trie_add_len_no_lock(trie, key, strlen(key), entry);
|
||||
}
|
||||
|
||||
TrieExitCode trie_add_len(Trie *trie, const char *key, size_t key_len,
|
||||
Entry *entry) {
|
||||
if (trie->file_path != NULL) {
|
||||
// Easiest way to make sure we don't add duplicate entries
|
||||
// We use an internal function that doesn't require a read lock, as we're
|
||||
// already inside a write lock
|
||||
if (trie_search_node(trie, key).child != NULL) {
|
||||
if (trie_search_node_len(trie, key, key_len).child != NULL) {
|
||||
return AlreadyPresent;
|
||||
}
|
||||
|
||||
|
@ -311,7 +315,11 @@ TrieExitCode trie_add(Trie *trie, const char *key, Entry *entry) {
|
|||
|
||||
// This function *should* always return Ok. Otherwise, the function would've
|
||||
// exited because the string was found in the trie.
|
||||
return trie_add_no_lock(trie, key, entry);
|
||||
return trie_add_len_no_lock(trie, key, key_len, entry);
|
||||
}
|
||||
|
||||
TrieExitCode trie_add(Trie *trie, const char *key, Entry *entry) {
|
||||
return trie_add_len(trie, key, strlen(key), entry);
|
||||
}
|
||||
|
||||
TrieExitCode trie_add_random(Trie *trie, char **key_ptr, Entry *entry,
|
||||
|
|
Loading…
Reference in New Issue