diff --git a/include/villas/api/node_request.hpp b/include/villas/api/node_request.hpp index 457e47973..6ed172ebf 100644 --- a/include/villas/api/node_request.hpp +++ b/include/villas/api/node_request.hpp @@ -32,11 +32,6 @@ namespace villas { namespace node { namespace api { -/* Forward declarations */ -class Session; -class Response; -class RequestFactory; - class NodeRequest : public Request { public: diff --git a/include/villas/api/path_request.hpp b/include/villas/api/path_request.hpp index a66e90ee8..2193caa94 100644 --- a/include/villas/api/path_request.hpp +++ b/include/villas/api/path_request.hpp @@ -32,11 +32,6 @@ namespace villas { namespace node { namespace api { -/* Forward declarations */ -class Session; -class Response; -class RequestFactory; - class PathRequest : public Request { public: diff --git a/include/villas/api/request.hpp b/include/villas/api/request.hpp index 00ab58ad7..4fbb40c48 100644 --- a/include/villas/api/request.hpp +++ b/include/villas/api/request.hpp @@ -53,28 +53,18 @@ protected: Logger logger; public: - std::string uri; std::smatch matches; + Session::Method method; json_t *body; RequestFactory *factory; - enum Method { - UNKNOWN, - GET, - POST, - DELETE, - OPTIONS, - PUT, - PATCH - } method; - Request(Session *s) : session(s), logger(logging.get("api:request")), + method(Session::Method::UNKNOWN), body(nullptr), - factory(nullptr), - method(Method::UNKNOWN) + factory(nullptr) { } virtual ~Request() @@ -106,7 +96,7 @@ public: make(Session *s) = 0; static Request * - make(Session *s, const std::string &uri, Request::Method meth); + create(Session *s); }; template diff --git a/include/villas/api/session.hpp b/include/villas/api/session.hpp index 4d73d0693..299c6342c 100644 --- a/include/villas/api/session.hpp +++ b/include/villas/api/session.hpp @@ -60,10 +60,24 @@ public: VERSION_2 = 2 }; + enum Method { + UNKNOWN, + GET, + POST, + DELETE, + OPTIONS, + PUT, + PATCH + }; + protected: enum State state; enum Version version; + std::string uri; + Method method; + unsigned long contentLength; + lws *wsi; Web *web; @@ -97,11 +111,14 @@ public: void execute(); void shutdown(); - static int protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); + static int + protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, void *user, void *in, size_t len); - int getRequestMethod(struct lws *wsi); + Method getRequestMethod() const; + std::string getRequestURI() const; - static std::string methodToString(int meth); + static std::string + methodToString(Method meth); }; diff --git a/lib/api.cpp b/lib/api.cpp index e5d1989de..cc4d20e60 100644 --- a/lib/api.cpp +++ b/lib/api.cpp @@ -34,10 +34,9 @@ using namespace villas::node; using namespace villas::node::api; InvalidMethod::InvalidMethod(Request *req) : - BadRequest( - fmt::format("The '{}' API endpoint does not support {} requests", - req->factory->getName(), Session::methodToString(req->method) - ) + BadRequest("The '{}' API endpoint does not support {} requests", + req->factory->getName(), + Session::methodToString(req->method) ) { } diff --git a/lib/api/request.cpp b/lib/api/request.cpp index fe2163abd..711b36ec6 100644 --- a/lib/api/request.cpp +++ b/lib/api/request.cpp @@ -28,8 +28,11 @@ using namespace villas; using namespace villas::node::api; -Request * RequestFactory::make(Session *s, const std::string &uri, Request::Method meth) +Request * RequestFactory::create(Session *s) { + auto uri = s->getRequestURI(); + auto meth = s->getRequestMethod(); + for (auto *rf : plugin::Registry::lookup()) { std::smatch mr; if (not rf->match(uri, mr)) @@ -40,13 +43,12 @@ Request * RequestFactory::make(Session *s, const std::string &uri, Request::Meth p->matches = mr; p->factory = rf; p->method = meth; - p->uri = uri; return p; } - throw BadRequest("Unknown API request", "{ s: s, s: i }", + throw BadRequest("Unknown API request", "{ s: s, s: s }", "uri", uri.c_str(), - "method", meth + "method", Session::methodToString(meth).c_str() ); } diff --git a/lib/api/requests/capabiltities.cpp b/lib/api/requests/capabiltities.cpp index d7945445e..52097c1b1 100644 --- a/lib/api/requests/capabiltities.cpp +++ b/lib/api/requests/capabiltities.cpp @@ -42,7 +42,7 @@ public: json_t *json_formats = json_array(); json_t *json_name; - if (method != Method::GET) + if (method != Session::Method::GET) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/config.cpp b/lib/api/requests/config.cpp index 9ca921655..8df87186d 100644 --- a/lib/api/requests/config.cpp +++ b/lib/api/requests/config.cpp @@ -38,7 +38,7 @@ public: { json_t *cfg = session->getSuperNode()->getConfig(); - if (method != Method::GET) + if (method != Session::Method::GET) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/node_action.cpp b/lib/api/requests/node_action.cpp index caaf8a539..8d4d16c05 100644 --- a/lib/api/requests/node_action.cpp +++ b/lib/api/requests/node_action.cpp @@ -43,7 +43,7 @@ public: virtual Response * execute() { - if (method != Method::POST) + if (method != Session::Method::POST) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/node_file.cpp b/lib/api/requests/node_file.cpp index 1e9a11477..d2b3e583b 100644 --- a/lib/api/requests/node_file.cpp +++ b/lib/api/requests/node_file.cpp @@ -39,7 +39,7 @@ public: virtual Response * execute() { - if (method != Method::GET && method != Method::POST) + if (method != Session::Method::GET && method != Session::Method::POST) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/node_info.cpp b/lib/api/requests/node_info.cpp index dc13576cf..f75fae589 100644 --- a/lib/api/requests/node_info.cpp +++ b/lib/api/requests/node_info.cpp @@ -42,7 +42,7 @@ public: virtual Response * execute() { - if (method != Method::GET) + if (method != Session::Method::GET) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/node_stats.cpp b/lib/api/requests/node_stats.cpp index 6b9cb9124..eac4a4e88 100644 --- a/lib/api/requests/node_stats.cpp +++ b/lib/api/requests/node_stats.cpp @@ -43,7 +43,7 @@ public: virtual Response * execute() { - if (method != Method::GET) + if (method != Session::Method::GET) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/node_stats_reset.cpp b/lib/api/requests/node_stats_reset.cpp index f33f293e2..d3e886739 100644 --- a/lib/api/requests/node_stats_reset.cpp +++ b/lib/api/requests/node_stats_reset.cpp @@ -43,7 +43,7 @@ public: virtual Response * execute() { - if (method != Method::POST) + if (method != Session::Method::POST) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/nodes.cpp b/lib/api/requests/nodes.cpp index 6d7658b7e..30975a79c 100644 --- a/lib/api/requests/nodes.cpp +++ b/lib/api/requests/nodes.cpp @@ -42,7 +42,7 @@ public: virtual Response * execute() { - if (method != Method::GET) + if (method != Session::Method::GET) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/path_action.cpp b/lib/api/requests/path_action.cpp index 394eec7ee..c93c8ad79 100644 --- a/lib/api/requests/path_action.cpp +++ b/lib/api/requests/path_action.cpp @@ -43,7 +43,7 @@ public: virtual Response * execute() { - if (method != Method::POST) + if (method != Session::Method::POST) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/path_info.cpp b/lib/api/requests/path_info.cpp index b63e716b6..d01b06edd 100644 --- a/lib/api/requests/path_info.cpp +++ b/lib/api/requests/path_info.cpp @@ -42,7 +42,7 @@ public: virtual Response * execute() { - if (method != Method::GET) + if (method != Session::Method::GET) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/paths.cpp b/lib/api/requests/paths.cpp index 41d5a0578..67b5841d8 100644 --- a/lib/api/requests/paths.cpp +++ b/lib/api/requests/paths.cpp @@ -43,7 +43,7 @@ public: virtual Response * execute() { - if (method != Method::GET) + if (method != Session::Method::GET) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/restart.cpp b/lib/api/requests/restart.cpp index 4033f2ddc..dbc94797b 100644 --- a/lib/api/requests/restart.cpp +++ b/lib/api/requests/restart.cpp @@ -63,7 +63,7 @@ public: int ret; json_error_t err; - if (method != Method::POST) + if (method != Session::Method::POST) throw InvalidMethod(this); const char *cfg = nullptr; diff --git a/lib/api/requests/shutdown.cpp b/lib/api/requests/shutdown.cpp index c58c50ba1..11ad7da64 100644 --- a/lib/api/requests/shutdown.cpp +++ b/lib/api/requests/shutdown.cpp @@ -37,7 +37,7 @@ public: virtual Response * execute() { - if (method != Method::POST) + if (method != Session::Method::POST) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/requests/status.cpp b/lib/api/requests/status.cpp index 97ec92c16..d58b565f1 100644 --- a/lib/api/requests/status.cpp +++ b/lib/api/requests/status.cpp @@ -42,7 +42,7 @@ public: struct lws_context *ctx = lws_get_context(s->wsi); char buf[4096]; - if (method != Method::GET) + if (method != Session::Method::GET) throw InvalidMethod(this); if (body != nullptr) diff --git a/lib/api/session.cpp b/lib/api/session.cpp index 3f02caea6..cb0437e71 100644 --- a/lib/api/session.cpp +++ b/lib/api/session.cpp @@ -37,6 +37,9 @@ using namespace villas::node; using namespace villas::node::api; Session::Session(lws *w) : + uri(), + method(Method::UNKNOWN), + contentLength(0), wsi(w), logger(logging.get("api:session")) { @@ -73,21 +76,21 @@ void Session::execute() { Request *r = request.exchange(nullptr); - logger->debug("Running API request: uri={}, method={}", r->uri, r->method); + logger->debug("Running API request: uri={}, method={}", uri, method); try { r->prepare(); response = r->execute(); - logger->debug("Completed API request: request={}", r->uri, r->method); + logger->debug("Completed API request: request={}", uri, method); } catch (const Error &e) { response = new ErrorResponse(this, e); - logger->warn("API request failed: uri={}, method={}, code={}: {}", r->uri, r->method, e.code, e.what()); + logger->warn("API request failed: uri={}, method={}, code={}: {}", uri, method, e.code, e.what()); } catch (const RuntimeError &e) { response = new ErrorResponse(this, e); - logger->warn("API request failed: uri={}, method={}: {}", r->uri, r->method, e.what()); + logger->warn("API request failed: uri={}, method={}: {}", uri, method, e.what()); } logger->debug("Ran pending API requests. Triggering on_writeable callback: wsi={}", (void *) wsi); @@ -124,17 +127,15 @@ void Session::open(void *in, size_t len) { int ret; char buf[32]; - unsigned long contentLength; - Request::Method meth; - std::string uri = reinterpret_cast(in); + uri = reinterpret_cast(in); try { - meth = (Request::Method) getRequestMethod(wsi); - if (meth == Request::Method::UNKNOWN) + auto method = getRequestMethod(); + if (method == Method::UNKNOWN) throw RuntimeError("Invalid request method"); - request = RequestFactory::make(this, uri, meth); + request = RequestFactory::create(this); ret = lws_hdr_copy(wsi, buf, sizeof(buf), WSI_TOKEN_HTTP_CONTENT_LENGTH); if (ret < 0) @@ -150,7 +151,7 @@ void Session::open(void *in, size_t len) * * We immediatly send headers and close the connection * without waiting for a POST body */ - if (meth == Request::Method::OPTIONS) + if (method == Method::OPTIONS) lws_callback_on_writable(wsi); /* This request has no body. * We can reply immediatly */ @@ -317,43 +318,48 @@ int Session::protocolCallback(struct lws *wsi, enum lws_callback_reasons reason, return 0; } -int Session::getRequestMethod(struct lws *wsi) +std::string Session::getRequestURI() const { - if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) - return Request::Method::GET; - else if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) - return Request::Method::POST; -#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) - else if (lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI)) - return Request::Method::PUT; - else if (lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI)) - return Request::Method::PATCH; - else if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) - return Request::Method::OPTIONS; -#endif - else - return Request::Method::UNKNOWN; + return uri; } -std::string Session::methodToString(int method) +Session::Method Session::getRequestMethod() const +{ + if (lws_hdr_total_length(wsi, WSI_TOKEN_GET_URI)) + return Method::GET; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_POST_URI)) + return Method::POST; +#if defined(LWS_WITH_HTTP_UNCOMMON_HEADERS) || defined(LWS_HTTP_HEADERS_ALL) + else if (lws_hdr_total_length(wsi, WSI_TOKEN_PUT_URI)) + return Method::PUT; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_PATCH_URI)) + return Method::PATCH; + else if (lws_hdr_total_length(wsi, WSI_TOKEN_OPTIONS_URI)) + return Method::OPTIONS; +#endif + else + return Method::UNKNOWN; +} + +std::string Session::methodToString(Method method) { switch (method) { - case Request::Method::POST: + case Method::POST: return "POST"; - case Request::Method::GET: + case Method::GET: return "GET"; - case Request::Method::DELETE: + case Method::DELETE: return "DELETE"; - case Request::Method::PUT: + case Method::PUT: return "PUT"; - case Request::Method::PATCH: + case Method::PATCH: return "GPATCHET"; - case Request::Method::OPTIONS: + case Method::OPTIONS: return "OPTIONS"; default: