diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2384fae --- /dev/null +++ b/.dockerignore @@ -0,0 +1,3 @@ +CMakeFiles/ +build/ +.git/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..576d8dd --- /dev/null +++ b/Dockerfile @@ -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 ] diff --git a/Makefile b/Makefile index 3db982f..66b402f 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ SRC_DIR := ./src TEST_DIR := test CORES != nproc -SRCS := $(shell find '$(SRC_DIR)' -iname '*.c') +SRCS := $(shell find '$(SRC_DIR)' -iname '*.cpp') # =====RECIPES===== @@ -31,7 +31,7 @@ prod: cmake-release .PHONY: run run: build - @ ./build/Debug/lander + @ LANDER_API_KEY=test ./build/Debug/lander .PHONY: clean clean: diff --git a/src/main.cpp b/src/main.cpp index e7ab79e..d96ddc5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,26 +4,50 @@ extern "C" { #include "ternarytrie.h" } -int main() -{ - TernaryTrie *trie = ternarytrie_init(); +int main() { + // Read in API key + char *api_key = getenv("LANDER_API_KEY"); - crow::SimpleApp app; + if (api_key == NULL) { + printf("No API key provided."); + return 1; + } - CROW_ROUTE(app, "/").methods(crow::HTTPMethod::Post) - ([trie](std::string s){ - ternarytrie_add(trie, s.c_str()); + TernaryTrie *trie = ternarytrie_init(); - return "added"; - }); - CROW_ROUTE(app, "/").methods(crow::HTTPMethod::Get) - ([trie](std::string s){ - if (ternarytrie_search(trie, s.c_str())) { - return "it's here"; - } + crow::SimpleApp app; - return "nope"; - }); + CROW_ROUTE(app, "/") + .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, "/") + .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(); } diff --git a/tries/CMakeLists.txt b/tries/CMakeLists.txt index d02e243..5955a9f 100644 --- a/tries/CMakeLists.txt +++ b/tries/CMakeLists.txt @@ -3,10 +3,10 @@ project(ternarytrie C) set(CMAKE_C_STANDARD 17) - add_library(ternarytrie STATIC src/ternarytrie.c) target_include_directories( ternarytrie PUBLIC $ ) +target_compile_options(ternarytrie PRIVATE -O3 -flto) diff --git a/tries/include/ternarytrie.h b/tries/include/ternarytrie.h index f33dc23..7d7a308 100644 --- a/tries/include/ternarytrie.h +++ b/tries/include/ternarytrie.h @@ -38,7 +38,7 @@ void ternarytrie_free(TernaryTrie* trie); * @param string * @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. @@ -47,7 +47,7 @@ bool ternarytrie_search(TernaryTrie* trie, const char* string); * @param string * @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. diff --git a/tries/src/ternarytrie.c b/tries/src/ternarytrie.c index bb3ce1c..59963bd 100644 --- a/tries/src/ternarytrie.c +++ b/tries/src/ternarytrie.c @@ -94,10 +94,14 @@ SearchResult ternarytrie_search_node(TernaryTrie *trie, const char *string) { * @param string string to look up * @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); - 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 * 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 if (string[0] == DELIMITER) { if (trie->root->type == 0) { trie->root->type = 1; + trie->root->payload = my_strdup(payload); trie->size++; return true; @@ -159,6 +164,8 @@ bool ternarytrie_add(TernaryTrie *trie, const char *string) { new_node->type = 1; } + new_node->payload = my_strdup(payload); + *node_ptr = new_node; trie->size++; @@ -181,6 +188,7 @@ bool ternarytrie_add(TernaryTrie *trie, const char *string) { } (*node_ptr)->type = 1; + (*node_ptr)->payload = my_strdup(payload); trie->size++; diff --git a/tries/src/ternarytrie_node.c b/tries/src/ternarytrie_node.c index 413e1ed..b6d355f 100644 --- a/tries/src/ternarytrie_node.c +++ b/tries/src/ternarytrie_node.c @@ -30,6 +30,7 @@ typedef struct ttnode { TernaryTrieInnerNode *root; char *string; } ptr; + char *payload; // What type of node this is // 0: regular non-representing node // 1: regular representing node @@ -100,6 +101,10 @@ void ttnode_free(TernaryTrieNode *node) { ttinode_free_cascade(node->ptr.root); } + if (node->payload != NULL) { + free(node->payload); + } + free(node); } @@ -213,8 +218,11 @@ void ttnode_split(TernaryTrieNode *node) { new_node->type = 1; } + new_node->payload = node->payload; + node->type = 0; node->size = 0; + node->payload = NULL; free(node->ptr.string); node->ptr.string = NULL;