From 2caefa9d96c7a5229728f51f38ca64a44326b03c Mon Sep 17 00:00:00 2001 From: Alex Hultman Date: Fri, 18 Jan 2019 16:35:25 +0100 Subject: [PATCH] We need HttpResponse::hasResponded --- src/App.h | 5 +++++ src/HttpContext.h | 25 +++++++++++++++++++++++++ src/HttpContextData.h | 10 ++++++++++ src/HttpParser.h | 2 +- src/HttpResponse.h | 10 ++++++++++ src/HttpResponseData.h | 7 ++----- 6 files changed, 53 insertions(+), 6 deletions(-) diff --git a/src/App.h b/src/App.h index 98ce0fd..dba6bd0 100644 --- a/src/App.h +++ b/src/App.h @@ -53,6 +53,11 @@ private: using StaticDispatch::static_dispatch; public: + /* Attaches a "filter" function to track socket connections/disconnections */ + void filter(fu2::unique_function *, int)> &&filterHandler) { + httpContext->filter(std::move(filterHandler)); + } + void registerTag() { } diff --git a/src/HttpContext.h b/src/HttpContext.h index 0d1dfc5..bc044df 100644 --- a/src/HttpContext.h +++ b/src/HttpContext.h @@ -70,6 +70,14 @@ private: /* Init socket ext */ new (static_dispatch(us_ssl_socket_ext, us_socket_ext)(s)) HttpResponseData; + /* Call filter */ + HttpContextData *httpContextData = getSocketContextDataS(s); + for (auto &f : httpContextData->filterHandlers) { + f((HttpResponse *) s, 1); + } + + // todo: handle filter closing the socket? + return s; }); @@ -78,6 +86,12 @@ private: /* Get socket ext */ HttpResponseData *httpResponseData = (HttpResponseData *) static_dispatch(us_ssl_socket_ext, us_socket_ext)(s); + /* Call filter */ + HttpContextData *httpContextData = getSocketContextDataS(s); + for (auto &f : httpContextData->filterHandlers) { + f((HttpResponse *) s, -1); + } + /* Signal broken HTTP request only if we have a pending request */ if (httpResponseData->onAborted) { httpResponseData->onAborted(); @@ -145,6 +159,13 @@ private: return nullptr; } + /* Returning from a request handler without responding or attaching an onAborted handler is ill-use */ + if (!((HttpResponse *) s)->hasResponded() && !httpResponseData->onAborted) { + /* Throw exception here? */ + std::cerr << "µWebSockets ill-use: Returning from a request handler without responding or attaching an abort handler is forbidden." << std::endl; + std::terminate(); + } + /* Continue parsing */ return s; @@ -269,6 +290,10 @@ public: static_dispatch(us_ssl_socket_context_free, us_socket_context_free)(getSocketContext()); } + void filter(fu2::unique_function *, int)> &&filterHandler) { + getSocketContextData()->filterHandlers.emplace_back(std::move(filterHandler)); + } + /* Register an HTTP route handler acording to URL pattern */ void onHttp(std::string method, std::string pattern, std::function *, uWS::HttpRequest *)> handler) { HttpContextData *httpContextData = getSocketContextData(); diff --git a/src/HttpContextData.h b/src/HttpContextData.h index 51f2d43..45642ae 100644 --- a/src/HttpContextData.h +++ b/src/HttpContextData.h @@ -21,6 +21,9 @@ #include "HttpRouter.h" #include +#include + +#include "f2/function2.hpp" namespace uWS { template struct HttpResponse; @@ -31,6 +34,13 @@ struct HttpContextData { template friend struct HttpContext; template friend struct HttpResponse; private: + std::vector *, int)>> filterHandlers; + + /*HttpContextData(const HttpContextData&) = delete; + HttpContextData() { + + }*/ + struct RouterData { HttpResponse *httpResponse; HttpRequest *httpRequest; diff --git a/src/HttpParser.h b/src/HttpParser.h index fdeb66d..6e91ae0 100644 --- a/src/HttpParser.h +++ b/src/HttpParser.h @@ -71,7 +71,7 @@ public: currentParameters = parameters; } - std::string_view getParameter(int index) { + std::string_view getParameter(unsigned int index) { if (currentParameters.first < index) { return {}; } else { diff --git a/src/HttpResponse.h b/src/HttpResponse.h index a848c6e..e8bb4a2 100644 --- a/src/HttpResponse.h +++ b/src/HttpResponse.h @@ -92,6 +92,8 @@ private: /* Terminating 0 chunk */ Super::write("\r\n0\r\n\r\n", 7); + // todo: here we reach the end, so remove onAborted, onWritable, and set HTTP_RESPONDED_TO + /* tryEnd can never fail when in chunked mode, since we do not have tryWrite (yet), only write */ Super::timeout(HTTP_TIMEOUT_S); return true; @@ -132,6 +134,8 @@ private: httpResponseData->onAborted = nullptr; /* Also remove onWritable so that we do not emit when draining behind the scenes. */ httpResponseData->onWritable = nullptr; + + // todo: set HTTP_RESPONDED_TO here and use in the emittance of new requests } return success; @@ -230,6 +234,12 @@ public: return httpResponseData->offset; } + /* Checking if we have fully responded and are ready for another request */ + bool hasResponded() { + // todo: implement + return true; + } + /* Attach handler for writable HTTP response */ HttpResponse *onWritable(fu2::unique_function &&handler) { HttpResponseData *httpResponseData = getHttpResponseData(); diff --git a/src/HttpResponseData.h b/src/HttpResponseData.h index 6245148..86b3481 100644 --- a/src/HttpResponseData.h +++ b/src/HttpResponseData.h @@ -38,17 +38,14 @@ private: HTTP_STATUS_CALLED = 1, // used HTTP_WRITE_CALLED = 2, // used HTTP_END_CALLED = 4, // used - HTTP_UPGRADED_TO_WEBSOCKET = 8, // not used + HTTP_RESPONDED_TO = 8, // used HTTP_ENDED_STREAM_OUT = 16 // not used }; /* Per socket event handlers */ fu2::unique_function onWritable; fu2::unique_function onAborted; - //std::function onData; - - fu2::unique_function inStream; - //std::function(int)> outStream; + fu2::unique_function inStream; // onData /* Outgoing offset */ int offset = 0;