144 lines
4.3 KiB
C++
144 lines
4.3 KiB
C++
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
|
|
#include "crow.h"
|
|
|
|
extern "C" {
|
|
#include "ternarytrie.h"
|
|
}
|
|
|
|
#define ENV(var, env_var) \
|
|
const char *_##var = getenv(env_var); \
|
|
if (_##var == NULL) { \
|
|
printf("Missing environment variable %s.\n", env_var); \
|
|
return 1; \
|
|
} \
|
|
const std::string var = std::string(_##var);
|
|
|
|
#define AUTH() \
|
|
std::string provided_api_key = req.get_header_value("X-Api-Key"); \
|
|
if (api_key.compare(provided_api_key) != 0) { \
|
|
return crow::response(crow::status::UNAUTHORIZED); \
|
|
}
|
|
|
|
int main() {
|
|
// Initialize random seed for generating URLs
|
|
srand(time(NULL));
|
|
|
|
ENV(api_key, "LANDER_API_KEY");
|
|
ENV(base_url, "LANDER_BASE_URL");
|
|
|
|
// Initialize trie and populate from data file
|
|
TernaryTrie *trie = ternarytrie_init();
|
|
|
|
std::string file_path = "lander.data";
|
|
|
|
std::cout << "Populating trie from file '" << file_path << "'..."
|
|
<< std::endl;
|
|
|
|
int count = ternarytrie_populate(trie, file_path.c_str());
|
|
|
|
if (count == -1) {
|
|
std::cout << "An error occured while populating the trie." << std::endl;
|
|
|
|
exit(1);
|
|
} else {
|
|
std::cout << "Added " << count << " entries to trie." << std::endl;
|
|
}
|
|
|
|
// Create pastes directory if not present
|
|
// TODO don't just ignore errors here
|
|
mkdir("pastes", 0700);
|
|
|
|
crow::SimpleApp app;
|
|
app.loglevel(crow::LogLevel::Info);
|
|
|
|
// Serve an entry
|
|
CROW_ROUTE(app, "/<string>")
|
|
.methods(crow::HTTPMethod::Get)(
|
|
[trie](crow::response &res, std::string key) {
|
|
Entry *entry = ternarytrie_search(trie, key.c_str());
|
|
|
|
if (entry != NULL) {
|
|
if (entry->type == Redirect) {
|
|
res.redirect(entry->string);
|
|
} else if (entry->type == Paste) {
|
|
res.set_static_file_info("pastes/" + key);
|
|
}
|
|
} else {
|
|
res.code = 404;
|
|
}
|
|
|
|
res.end();
|
|
});
|
|
|
|
// Add a new Redirect with a randomly generated key
|
|
CROW_ROUTE(app, "/s/")
|
|
.methods(crow::HTTPMethod::Post)(
|
|
[api_key, base_url, trie](const crow::request req) {
|
|
AUTH();
|
|
|
|
Entry *new_entry = entry_new(Redirect, req.body.c_str());
|
|
char *key = ternarytrie_add_random(trie, new_entry);
|
|
|
|
if (key == NULL) {
|
|
return crow::response(crow::status::INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
std::string res = base_url + key;
|
|
free(key);
|
|
|
|
return crow::response(res);
|
|
});
|
|
|
|
// Add a new Redirect with a given path
|
|
CROW_ROUTE(app, "/s/<string>")
|
|
.methods(crow::HTTPMethod::Post)(
|
|
[api_key, base_url, trie](const crow::request &req, std::string key) {
|
|
AUTH();
|
|
|
|
Entry *new_entry = entry_new(Redirect, req.body.c_str());
|
|
|
|
bool added = ternarytrie_add(trie, key.c_str(), new_entry);
|
|
|
|
if (!added) {
|
|
return crow::response(crow::status::CONFLICT);
|
|
}
|
|
|
|
return crow::response(base_url + key);
|
|
});
|
|
|
|
// Add a new Paste with a randomly generated key
|
|
CROW_ROUTE(app, "/p/")
|
|
.methods(crow::HTTPMethod::Post)(
|
|
[api_key, base_url, trie](const crow::request &req) {
|
|
AUTH();
|
|
|
|
Entry *new_entry = entry_new(Paste, "");
|
|
char *key = ternarytrie_add_random(trie, new_entry);
|
|
|
|
if (key == NULL) {
|
|
return crow::response(crow::status::INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
// Write paste contents to file
|
|
std::fstream file;
|
|
file.open(std::string("pastes/") + key, std::ios_base::out);
|
|
|
|
if (!file.is_open()) {
|
|
free(key);
|
|
return crow::response(crow::status::INTERNAL_SERVER_ERROR);
|
|
}
|
|
|
|
file << req.body;
|
|
file.close();
|
|
|
|
std::string res = base_url + key;
|
|
free(key);
|
|
|
|
return crow::response(res);
|
|
});
|
|
|
|
app.port(18080).multithreaded().run();
|
|
}
|