From 9829f7fb37c129ac4945cfd58355959270d73d8f Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Tue, 22 Jan 2019 18:30:25 +0100 Subject: [PATCH] Add concept of route yielding --- misc/main.cpp | 2 +- src/App.h | 4 ++-- src/HttpContext.h | 9 ++++++--- src/HttpParser.h | 10 ++++++++++ 4 files changed, 19 insertions(+), 6 deletions(-) diff --git a/misc/main.cpp b/misc/main.cpp index 1536e36..4069aac 100644 --- a/misc/main.cpp +++ b/misc/main.cpp @@ -31,7 +31,7 @@ int main(int argc, char **argv) { /* Use this route to signal stop listening */ us_listen_socket_close(token); token = nullptr; - }).ws("/ws", { + }).ws("/*", { /* Settings */ .compression = uWS::DEDICATED_COMPRESSOR, .maxPayloadLength = 16 * 1024 * 1024, diff --git a/src/App.h b/src/App.h index 085fcba..f7afcf6 100644 --- a/src/App.h +++ b/src/App.h @@ -217,8 +217,8 @@ public: /* We do not need to check for any close or shutdown here as we immediately return from get handler */ } else { - /* For now we do not support having HTTP and websocket routes on the same URL */ - res->close(); + /* Tell the router that we did not handle this request */ + req->setYield(true); } })); } diff --git a/src/HttpContext.h b/src/HttpContext.h index ac4d07a..87c221a 100644 --- a/src/HttpContext.h +++ b/src/HttpContext.h @@ -145,8 +145,7 @@ private: /* Route the method and URL in two passes */ typename HttpContextData::RouterData routerData = {(HttpResponse *) s, httpRequest}; - bool firstPass = httpContextData->router.route(httpRequest->getMethod(), httpRequest->getUrl(), routerData); - if (!firstPass) { + if (!httpContextData->router.route(httpRequest->getMethod(), httpRequest->getUrl(), routerData)) { /* If first pass failed, we try and match by "any" method */ if (!httpContextData->router.route("*", httpRequest->getUrl(), routerData)) { /* If second pass fail, we have to force close this socket as we have no handler for it */ @@ -311,10 +310,14 @@ public: HttpContextData *httpContextData = getSocketContextData(); httpContextData->router.add(method, pattern, [handler](typename HttpContextData::RouterData &user, std::pair params) { + user.httpRequest->setYield(false); user.httpRequest->setParameters(params); handler(user.httpResponse, user.httpRequest); - // for now all routes handle it + /* If any handler yielded, the router will keep looking for a suitable handler. */ + if (user.httpRequest->getYield()) { + return false; + } return true; }); } diff --git a/src/HttpParser.h b/src/HttpParser.h index 6e91ae0..bd59743 100644 --- a/src/HttpParser.h +++ b/src/HttpParser.h @@ -37,10 +37,20 @@ private: std::string_view key, value; } headers[MAX_HEADERS]; int querySeparator; + bool didYield; std::pair currentParameters; public: + bool getYield() { + return didYield; + } + + /* If you do not want to handle this route */ + void setYield(bool yield) { + didYield = yield; + } + std::string_view getHeader(std::string_view header) { for (Header *h = headers; (++h)->key.length(); ) { if (h->key.length() == header.length() && !strncmp(h->key.data(), header.data(), header.length())) {