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