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 | ||||
| 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: | ||||
|  |  | |||
							
								
								
									
										58
									
								
								src/main.cpp
								
								
								
								
							
							
						
						
									
										58
									
								
								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, "/<string>").methods(crow::HTTPMethod::Post) | ||||
|     ([trie](std::string s){ | ||||
|         ternarytrie_add(trie, s.c_str()); | ||||
|   TernaryTrie *trie = ternarytrie_init(); | ||||
| 
 | ||||
|         return "added"; | ||||
|     }); | ||||
|     CROW_ROUTE(app, "/<string>").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, "/<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) | ||||
| 
 | ||||
| 
 | ||||
| add_library(ternarytrie STATIC src/ternarytrie.c) | ||||
| 
 | ||||
| target_include_directories( | ||||
|     ternarytrie PUBLIC | ||||
|     $<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 | ||||
|  * @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. | ||||
|  |  | |||
|  | @ -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++; | ||||
| 
 | ||||
|  |  | |||
|  | @ -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; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue