/** * Digital Voice Modem - Host Software * GPLv2 Open Source. Use is subject to license terms. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * @package DVM / Host Software * */ // // Based on code from the CRUD project. (https://github.com/venediktov/CRUD) // Licensed under the BPL-1.0 License (https://opensource.org/license/bsl1-0-html) // /* * Copyright (c) 2003-2013 Christopher M. Kohlhoff * Copyright (C) 2023 by Bryan Biedenkapp N2PLL * * Permission is hereby granted, free of charge, to any person or organization * obtaining a copy of the software and accompanying documentation covered by * this license (the “Software”) to use, reproduce, display, distribute, execute, * and transmit the Software, and to prepare derivative works of the Software, and * to permit third-parties to whom the Software is furnished to do so, all subject * to the following: * * The copyright notices in the Software and this entire statement, including the * above license grant, this restriction and the following disclaimer, must be included * in all copies of the Software, in whole or in part, and all derivative works of the * Software, unless such copies or derivative works are solely in the form of * machine-executable object code generated by a source language processor. * * THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR ANYONE * DISTRIBUTING THE SOFTWARE BE LIABLE FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #if !defined(__REST__DISPATCHER_H__) #define __REST__DISPATCHER_H__ #include "Defines.h" #include "network/rest/http/HTTPRequest.h" #include "network/rest/http/HTTPReply.h" #include #include #include #include #include namespace network { namespace rest { // --------------------------------------------------------------------------- // Structure Declaration // // --------------------------------------------------------------------------- struct RequestMatch : std::smatch { /// Initializes a new instance of the RequestMatch structure. RequestMatch(const std::smatch& m, const std::string& d) : std::smatch(m), data(d) { /* stub */ } std::string data; }; // --------------------------------------------------------------------------- // Structure Declaration // // --------------------------------------------------------------------------- template struct RequestMatcher { typedef std::function RequestHandlerType; /// Initializes a new instance of the RequestMatcher structure. explicit RequestMatcher(const std::string& expression) : m_expression(expression), m_isRegEx(false) { /* stub */ } /// RequestMatcher& get(RequestHandlerType handler) { m_handlers["GET"] = handler; return *this; } /// RequestMatcher& post(RequestHandlerType handler) { m_handlers["POST"] = handler; return *this; } /// RequestMatcher& put(RequestHandlerType handler) { m_handlers["PUT"] = handler; return *this; } /// RequestMatcher& del(RequestHandlerType handler) { m_handlers["DELETE"] = handler; return *this; } /// RequestMatcher& options(RequestHandlerType handler) { m_handlers["OPTIONS"] = handler; return *this; } bool regex() const { return m_isRegEx; } void setRegEx(bool regEx) { m_isRegEx = regEx; } /// template void handleRequest(const Request& request, Reply& reply, const std::smatch &what) { // dispatching to matching based on handler RequestMatch match(what, request.data); auto& handler = m_handlers[request.method]; if (handler) { handler(reply, match); } } private: std::string m_expression; bool m_isRegEx; std::map m_handlers; }; // --------------------------------------------------------------------------- // Class Declaration // This class implements RESTful web request dispatching. // --------------------------------------------------------------------------- template class RequestDispatcher { typedef RequestMatcher MatcherType; public: /// Initializes a new instance of the RequestDispatcher class. RequestDispatcher() : m_basePath() { /* stub */ } /// Initializes a new instance of the RequestDispatcher class. RequestDispatcher(const std::string& basePath) : m_basePath(basePath) { /* stub */ } /// MatcherType& match(const std::string& expression) { MatcherTypePtr& p = m_matchers[expression]; if (!p) { p = std::make_shared(expression); } return *p; } /// void handleRequest(const Request& request, Reply& reply) { for (const auto& matcher : m_matchers) { std::smatch what; if (!matcher.second->regex()) { if (request.uri.find(matcher.first) != std::string::npos) { //what = matcher.first; matcher.second->handleRequest(request, reply, what); } else { reply = http::HTTPReply::stockReply(http::HTTPReply::BAD_REQUEST); } } else { if (std::regex_match(request.uri, what, std::regex(matcher.first))) { matcher.second->handleRequest(request, reply, what); } else { reply = http::HTTPReply::stockReply(http::HTTPReply::BAD_REQUEST); } } } } private: typedef std::shared_ptr MatcherTypePtr; std::string m_basePath; std::map m_matchers; }; typedef RequestDispatcher DefaultRequestDispatcher; } // namespace rest } // namespace network #endif // __REST__DISPATCHER_H__