Basic working version without persistent storage
parent
cae62ce7d2
commit
a2fcbb4224
|
@ -0,0 +1,3 @@
|
||||||
|
CMakeFiles/
|
||||||
|
build/
|
||||||
|
.git/
|
|
@ -0,0 +1,15 @@
|
||||||
|
FROM alpine:3.16.3 AS builder
|
||||||
|
|
||||||
|
RUN apk add --update --no-cache \
|
||||||
|
build-base \
|
||||||
|
make \
|
||||||
|
cmake \
|
||||||
|
boost1.78-static
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY . ./
|
||||||
|
|
||||||
|
RUN make prod && \
|
||||||
|
strip build/Release/lander && \
|
||||||
|
[ "$(readelf -d build/Release/lander | grep NEEDED | wc -l)" = 0 ]
|
4
Makefile
4
Makefile
|
@ -4,7 +4,7 @@ SRC_DIR := ./src
|
||||||
TEST_DIR := test
|
TEST_DIR := test
|
||||||
CORES != nproc
|
CORES != nproc
|
||||||
|
|
||||||
SRCS := $(shell find '$(SRC_DIR)' -iname '*.c')
|
SRCS := $(shell find '$(SRC_DIR)' -iname '*.cpp')
|
||||||
|
|
||||||
|
|
||||||
# =====RECIPES=====
|
# =====RECIPES=====
|
||||||
|
@ -31,7 +31,7 @@ prod: cmake-release
|
||||||
|
|
||||||
.PHONY: run
|
.PHONY: run
|
||||||
run: build
|
run: build
|
||||||
@ ./build/Debug/lander
|
@ LANDER_API_KEY=test ./build/Debug/lander
|
||||||
|
|
||||||
.PHONY: clean
|
.PHONY: clean
|
||||||
clean:
|
clean:
|
||||||
|
|
58
src/main.cpp
58
src/main.cpp
|
@ -4,26 +4,50 @@ extern "C" {
|
||||||
#include "ternarytrie.h"
|
#include "ternarytrie.h"
|
||||||
}
|
}
|
||||||
|
|
||||||
int main()
|
int main() {
|
||||||
{
|
// Read in API key
|
||||||
TernaryTrie *trie = ternarytrie_init();
|
char *api_key = getenv("LANDER_API_KEY");
|
||||||
|
|
||||||
crow::SimpleApp app;
|
if (api_key == NULL) {
|
||||||
|
printf("No API key provided.");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
CROW_ROUTE(app, "/<string>").methods(crow::HTTPMethod::Post)
|
TernaryTrie *trie = ternarytrie_init();
|
||||||
([trie](std::string s){
|
|
||||||
ternarytrie_add(trie, s.c_str());
|
|
||||||
|
|
||||||
return "added";
|
crow::SimpleApp app;
|
||||||
});
|
|
||||||
CROW_ROUTE(app, "/<string>").methods(crow::HTTPMethod::Get)
|
|
||||||
([trie](std::string s){
|
|
||||||
if (ternarytrie_search(trie, s.c_str())) {
|
|
||||||
return "it's here";
|
|
||||||
}
|
|
||||||
|
|
||||||
return "nope";
|
CROW_ROUTE(app, "/<string>")
|
||||||
});
|
.methods(crow::HTTPMethod::Post)(
|
||||||
|
[api_key, trie](const crow::request &req, std::string s) {
|
||||||
|
// Authenticate request
|
||||||
|
std::string provided_api_key = req.get_header_value("X-Api-Key");
|
||||||
|
|
||||||
app.port(18080).multithreaded().run();
|
if (strcmp(api_key, provided_api_key.c_str()) != 0) {
|
||||||
|
return crow::response(crow::status::UNAUTHORIZED);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool res = ternarytrie_add(trie, s.c_str(), req.body.c_str());
|
||||||
|
|
||||||
|
if (!res) {
|
||||||
|
return crow::response(crow::status::CONFLICT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return crow::response(crow::status::NO_CONTENT);
|
||||||
|
});
|
||||||
|
CROW_ROUTE(app, "/<string>")
|
||||||
|
.methods(crow::HTTPMethod::Get)(
|
||||||
|
[trie](crow::response &res, std::string s) {
|
||||||
|
char *payload = ternarytrie_search(trie, s.c_str());
|
||||||
|
|
||||||
|
if (payload != NULL) {
|
||||||
|
res.redirect(payload);
|
||||||
|
} else {
|
||||||
|
res.code = 404;
|
||||||
|
}
|
||||||
|
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
app.port(18080).multithreaded().run();
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,10 @@ project(ternarytrie C)
|
||||||
|
|
||||||
set(CMAKE_C_STANDARD 17)
|
set(CMAKE_C_STANDARD 17)
|
||||||
|
|
||||||
|
|
||||||
add_library(ternarytrie STATIC src/ternarytrie.c)
|
add_library(ternarytrie STATIC src/ternarytrie.c)
|
||||||
|
|
||||||
target_include_directories(
|
target_include_directories(
|
||||||
ternarytrie PUBLIC
|
ternarytrie PUBLIC
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||||
)
|
)
|
||||||
|
target_compile_options(ternarytrie PRIVATE -O3 -flto)
|
||||||
|
|
|
@ -38,7 +38,7 @@ void ternarytrie_free(TernaryTrie* trie);
|
||||||
* @param string
|
* @param string
|
||||||
* @return true if the string is contained within this trie, false otherwise
|
* @return true if the string is contained within this trie, false otherwise
|
||||||
*/
|
*/
|
||||||
bool ternarytrie_search(TernaryTrie* trie, const char* string);
|
char * ternarytrie_search(TernaryTrie* trie, const char* string);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a string to this trie.
|
* Add a string to this trie.
|
||||||
|
@ -47,7 +47,7 @@ bool ternarytrie_search(TernaryTrie* trie, const char* string);
|
||||||
* @param string
|
* @param string
|
||||||
* @return true if the trie was changed by this operation, false if it was already present
|
* @return true if the trie was changed by this operation, false if it was already present
|
||||||
*/
|
*/
|
||||||
bool ternarytrie_add(TernaryTrie* trie, const char* string);
|
bool ternarytrie_add(TernaryTrie* trie, const char* string, const char *payload);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove a string from this trie.
|
* Remove a string from this trie.
|
||||||
|
|
|
@ -94,10 +94,14 @@ SearchResult ternarytrie_search_node(TernaryTrie *trie, const char *string) {
|
||||||
* @param string string to look up
|
* @param string string to look up
|
||||||
* @return true if the string is present in the trie, false otherwise
|
* @return true if the string is present in the trie, false otherwise
|
||||||
*/
|
*/
|
||||||
bool ternarytrie_search(TernaryTrie *trie, const char *string) {
|
char * ternarytrie_search(TernaryTrie *trie, const char *string) {
|
||||||
SearchResult res = ternarytrie_search_node(trie, string);
|
SearchResult res = ternarytrie_search_node(trie, string);
|
||||||
|
|
||||||
return res.child != NULL;
|
if (res.child != NULL) {
|
||||||
|
return res.child->payload;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,11 +112,12 @@ bool ternarytrie_search(TernaryTrie *trie, const char *string) {
|
||||||
* @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
|
||||||
*/
|
*/
|
||||||
bool ternarytrie_add(TernaryTrie *trie, const char *string) {
|
bool ternarytrie_add(TernaryTrie *trie, const char *string, const char *payload) {
|
||||||
// Edge case for empty string
|
// Edge case for empty string
|
||||||
if (string[0] == DELIMITER) {
|
if (string[0] == DELIMITER) {
|
||||||
if (trie->root->type == 0) {
|
if (trie->root->type == 0) {
|
||||||
trie->root->type = 1;
|
trie->root->type = 1;
|
||||||
|
trie->root->payload = my_strdup(payload);
|
||||||
trie->size++;
|
trie->size++;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -159,6 +164,8 @@ bool ternarytrie_add(TernaryTrie *trie, const char *string) {
|
||||||
new_node->type = 1;
|
new_node->type = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_node->payload = my_strdup(payload);
|
||||||
|
|
||||||
*node_ptr = new_node;
|
*node_ptr = new_node;
|
||||||
|
|
||||||
trie->size++;
|
trie->size++;
|
||||||
|
@ -181,6 +188,7 @@ bool ternarytrie_add(TernaryTrie *trie, const char *string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
(*node_ptr)->type = 1;
|
(*node_ptr)->type = 1;
|
||||||
|
(*node_ptr)->payload = my_strdup(payload);
|
||||||
|
|
||||||
trie->size++;
|
trie->size++;
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@ typedef struct ttnode {
|
||||||
TernaryTrieInnerNode *root;
|
TernaryTrieInnerNode *root;
|
||||||
char *string;
|
char *string;
|
||||||
} ptr;
|
} ptr;
|
||||||
|
char *payload;
|
||||||
// What type of node this is
|
// What type of node this is
|
||||||
// 0: regular non-representing node
|
// 0: regular non-representing node
|
||||||
// 1: regular representing node
|
// 1: regular representing node
|
||||||
|
@ -100,6 +101,10 @@ void ttnode_free(TernaryTrieNode *node) {
|
||||||
ttinode_free_cascade(node->ptr.root);
|
ttinode_free_cascade(node->ptr.root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node->payload != NULL) {
|
||||||
|
free(node->payload);
|
||||||
|
}
|
||||||
|
|
||||||
free(node);
|
free(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,8 +218,11 @@ void ttnode_split(TernaryTrieNode *node) {
|
||||||
new_node->type = 1;
|
new_node->type = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
new_node->payload = node->payload;
|
||||||
|
|
||||||
node->type = 0;
|
node->type = 0;
|
||||||
node->size = 0;
|
node->size = 0;
|
||||||
|
node->payload = NULL;
|
||||||
|
|
||||||
free(node->ptr.string);
|
free(node->ptr.string);
|
||||||
node->ptr.string = NULL;
|
node->ptr.string = NULL;
|
||||||
|
|
Loading…
Reference in New Issue