//! \addtogroup HTTP //! \~\file pihttpserver.h //! \brief High-level HTTP server implementation //! \~english High-level HTTP server with path-based routing and handler registration //! \~russian Высокоуровневый HTTP сервер с маршрутизацией по путям и регистрацией обработчиков /* PIP - Platform Independent Primitives High-level HTTP server implementation Ivan Pelipenko peri4ko@yandex.ru This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this program. If not, see . */ #ifndef PIHTTPSERVER_H #define PIHTTPSERVER_H #include "microhttpd_server.h" //! \~\ingroup HTTP //! \~\brief //! \~english HTTP server that routes requests by method and path pattern. //! \~russian HTTP-сервер, маршрутизирующий запросы по методу и шаблону пути. //! //! \~\details //! \~english Registered paths are matched segment by segment. The router supports fixed segments, //! \c * for any single segment, \c ** for any tail, and \c {name} placeholders that populate //! \a PIHTTP::MessageConst::pathArguments(). //! \~russian Зарегистрированные пути сопоставляются посегментно. Маршрутизатор поддерживает //! фиксированные сегменты, \c * для любого одного сегмента, \c ** для любого хвоста и //! заполнители \c {name}, которые заполняют \a PIHTTP::MessageConst::pathArguments(). class PIP_HTTP_SERVER_EXPORT PIHTTPServer: public MicrohttpdServer { PIOBJECT_SUBCLASS(PIHTTPServer, MicrohttpdServer) public: //! \~english Creates a server with built-in path dispatching. //! \~russian Создает сервер со встроенной диспетчеризацией по путям. PIHTTPServer(); //! \~english Destroys the server and stops listening if needed. //! \~russian Удаляет сервер и при необходимости останавливает прослушивание. virtual ~PIHTTPServer(); //! \~english Request handler used by registered routes and fallback processing. //! \~russian Обработчик запроса, используемый зарегистрированными маршрутами и fallback-обработкой. using RequestFunction = std::function; //! \~english Registers a handler for the specified path pattern and HTTP method. //! \~russian Регистрирует обработчик для указанного шаблона пути и HTTP-метода. bool registerPath(const PIString & path, PIHTTP::Method method, RequestFunction functor); //! \~english Registers an object method as a handler for the specified path pattern and HTTP method. //! \~russian Регистрирует метод объекта как обработчик для указанного шаблона пути и HTTP-метода. template bool registerPath(const PIString & path, PIHTTP::Method method, T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) { return registerPath(path, method, [o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); }); } //! \~english Registers a fallback handler for requests that did not match any route. //! \~russian Регистрирует fallback-обработчик для запросов, не совпавших ни с одним маршрутом. void registerUnhandled(RequestFunction functor); //! \~english Registers an object method as the fallback handler for unmatched requests. //! \~russian Регистрирует метод объекта как fallback-обработчик для несовпавших запросов. template void registerUnhandled(T * o, PIHTTP::MessageMutable (T::*function)(const PIHTTP::MessageConst &)) { registerUnhandled([o, function](const PIHTTP::MessageConst & m) { return (o->*function)(m); }); } //! \~english Unregisters the handler for the specified path pattern and HTTP method. //! \~russian Удаляет обработчик для указанного шаблона пути и HTTP-метода. void unregisterPath(const PIString & path, PIHTTP::Method method); //! \~english Unregisters all handlers bound to the specified path pattern. //! \~russian Удаляет все обработчики, привязанные к указанному шаблону пути. void unregisterPath(const PIString & path); //! \~english Adds a header that will be copied to all replies produced by this router. //! \~russian Добавляет заголовок, который будет копироваться во все ответы этого маршрутизатора. void addReplyHeader(const PIString & name, const PIString & value) { reply_headers[name] = value; } //! \~english Removes a previously added common reply header. //! \~russian Удаляет ранее добавленный общий заголовок ответа. void removeReplyHeader(const PIString & name) { reply_headers.remove(name); } //! \~english Clears all custom headers added to router replies. //! \~russian Очищает все пользовательские заголовки, добавленные к ответам маршрутизатора. void clearReplyHeaders() { reply_headers.clear(); } private: struct PathElement { enum class Type { Invalid = 0x01, Fixed = 0x02, Arguments = 0x04, AnyOne = 0x08, AnyPart = 0x10, AnyMany = 0x20 }; Type type = Type::Fixed; PIString source; PIStringList parts; PIMap arguments; PathElement(const PIString & reg = {}); bool match(const PIString & in, PIMap & ext_args) const; uint priority() const; }; struct Endpoint { PIStringList path; PIHTTP::Method method = PIHTTP::Method::Unknown; RequestFunction function; PIFlags path_types; PIVector prepared_path; uint priority = 0; bool create(const PIString & p); bool match(const PIStringList & in_path, PIMap & ext_args) const; }; static PIStringList splitPath(const PIString & path); PIMap reply_headers; PIMap> endpoints; RequestFunction unhandled; }; #endif