diff --git a/misc/main.cpp b/misc/main.cpp index cfd33cb..9cb1cd1 100644 --- a/misc/main.cpp +++ b/misc/main.cpp @@ -12,10 +12,20 @@ int main(int argc, char **argv) { .cert_file_name = "/home/alexhultman/uWebSockets/misc/ssl/cert.pem", .dh_params_file_name = "/home/alexhultman/dhparams.pem", .passphrase = "1234" - }*/).get("/hello", [asyncFileStreamer](auto *res, auto *req) { + }*/).get("/*", [](auto *res, auto *req) { + + res->end("GET /WILDCARD"); + + }).post("/hello", [asyncFileStreamer](auto *res, auto *req) { // depending on the file type we want to also add mime! - asyncFileStreamer->streamFile(res, req->getUrl()); + //asyncFileStreamer->streamFile(res, req->getUrl()); + + res->end("POST /hello"); + + }).get("/hello", [](auto *res, auto *req) { + + res->end("GET /hello"); }).unhandled([](auto *res, auto *req) { diff --git a/src/App.h b/src/App.h index 84d46e8..d6e9307 100644 --- a/src/App.h +++ b/src/App.h @@ -32,6 +32,11 @@ public: return *this; } + TemplatedApp &post(std::string pattern, std::function *, HttpRequest *)> handler) { + httpContext->onPost(pattern, handler); + return *this; + } + TemplatedApp &unhandled(std::function *, HttpRequest *)> handler) { httpContext->onUnhandled(handler); return *this; diff --git a/src/HttpContext.h b/src/HttpContext.h index 9e81255..00c3e68 100644 --- a/src/HttpContext.h +++ b/src/HttpContext.h @@ -111,7 +111,7 @@ private: typename uWS::HttpContextData::UserData userData = { (HttpResponse *) s, httpRequest }; - httpContextData->router.route("get", 3, httpRequest->getUrl().data(), httpRequest->getUrl().length(), &userData); + httpContextData->router.route(httpRequest->getMethod().data(), httpRequest->getMethod().length(), httpRequest->getUrl().data(), httpRequest->getUrl().length(), &userData); // here we can be closed and in shutdown? @@ -220,6 +220,14 @@ public: }); } + void onPost(std::string pattern, std::function *, uWS::HttpRequest *)> handler) { + HttpContextData *httpContextData = getSocketContextData(); + + httpContextData->router.add("post", pattern.c_str(), [handler](typename HttpContextData::UserData *user, auto *args) { + handler(user->httpResponse, user->httpRequest); + }); + } + void onUnhandled(std::function *, uWS::HttpRequest *)> handler) { HttpContextData *httpContextData = getSocketContextData(); diff --git a/src/HttpParser.h b/src/HttpParser.h index 7cb9af6..e6c5385 100644 --- a/src/HttpParser.h +++ b/src/HttpParser.h @@ -39,6 +39,10 @@ public: return std::string_view(headers->value.data(), querySeparator); } + std::string_view getMethod() { + return std::string_view(headers->key.data(), headers->key.length()); + } + std::string_view getQuery() { return std::string_view(headers->value.data() + querySeparator, headers->value.length() - querySeparator); } diff --git a/src/HttpRouter.h b/src/HttpRouter.h index bd82e39..124f4eb 100644 --- a/src/HttpRouter.h +++ b/src/HttpRouter.h @@ -24,14 +24,13 @@ private: std::string name; std::map children; short handler; - }; + } tree; - Node *tree = new Node({"GET", {}, -1}); std::string compiled_tree; void add(std::vector route, short handler) { //std::cout << "add" << std::endl; - Node *parent = tree; + Node *parent = &tree; for (std::string node : route) { //std::cout << "Node: <" << node << ">" << std::endl; @@ -42,6 +41,7 @@ private: } } + // serialize tree unsigned short compile_tree(Node *n) { unsigned short nodeLength = 6 + n->name.length(); for (auto c : n->children) { @@ -99,18 +99,24 @@ private: return stop ? stop : end; } - // should take method also! - inline int lookup(const char *url, int length) { + inline int lookup(const char *method, int method_length, const char *url, int length) { // all urls start with / url++; length--; const char *treeStart = (char *) compiled_tree.data(); - bool foundWildcard = false; + // step1: lookup this method (we lookup treeStart) + treeStart = find_node(treeStart, method, method_length, &foundWildcard); + if (treeStart == 0) { + //std::cout << "We do not even have this method!" << std::endl; + return -1; + } + const char *stop, *start = url, *end_ptr = url + length; do { + // start and stop are pointers in the URL we are getting, end_ptr is the end of url stop = getNextSegment(start, end_ptr); //std::cout << "Matching(" << std::string(start, stop - start) << ")" << std::endl; @@ -148,22 +154,17 @@ public: } std::vector nodes; - //nodes.push_back(method); + nodes.push_back(method); const char *stop, *start = pattern, *end_ptr = pattern + strlen(pattern); do { stop = getNextSegment(start, end_ptr); - //std::cout << "Segment(" << std::string(start, stop - start) << ")" << std::endl; - nodes.push_back(std::string(start, stop - start)); - start = stop + 1; } while (stop != end_ptr); - - // if pattern starts with / then move 1+ and run inline slash parser - + // add this path to the tree add(nodes, handlers.size()); handlers.push_back(handler); @@ -173,19 +174,20 @@ public: void compile() { compiled_tree.clear(); - compile_tree(tree); + compile_tree(&tree); } void route(const char *method, unsigned int method_length, const char *url, unsigned int url_length, USERDATA userData) { - int index = lookup(url, url_length); + // todo: simplify so that unhandled is 0! + int index = lookup(method, method_length, url, url_length); if (index != -1) { handlers[index](userData, ¶ms); } else { - std::cout << "Did not find route for URL: " << std::string_view(url, url_length) << std::endl; unhandledHandler(userData, ¶ms); } + // will this counter the reserve? params.clear(); } };