|
@@ -50,8 +50,8 @@ namespace kbf {
|
|
|
* @tparam T Controller class
|
|
|
*/
|
|
|
template<class T>
|
|
|
- void attach() {
|
|
|
- static_assert(std::is_base_of<Controller, T>::value, "attach(): type must be a Controller");
|
|
|
+ void controller() {
|
|
|
+ static_assert(std::is_base_of<Controller, T>::value, "controller(): type must be a Controller");
|
|
|
|
|
|
Controller *controller = new T();
|
|
|
|
|
@@ -62,14 +62,38 @@ namespace kbf {
|
|
|
handler = Controller::responseSentHandler;
|
|
|
}
|
|
|
|
|
|
- server.route({kbf::http::Method::GET, controller->path, handleGet, controller, handler});
|
|
|
- server.route({kbf::http::Method::POST, controller->path, handlePost, controller, handler});
|
|
|
+ auto *arg = new HandlerArg{*this, *controller};
|
|
|
+ server.route({http::Method::GET, controller->path, handleGet, arg, handler});
|
|
|
+ server.route({http::Method::POST, controller->path, handlePost, arg, handler});
|
|
|
}
|
|
|
|
|
|
+ class Middleware;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @brief Adds a #Middleware to the service.
|
|
|
+ *
|
|
|
+ * @tparam T Middleware class
|
|
|
+ */
|
|
|
+ template<class T>
|
|
|
+ void middleware() {
|
|
|
+ static_assert(std::is_base_of<Middleware, T>::value, "middleware(): type must be a Middleware");
|
|
|
+ middlewares.push_back(new T());
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @brief Continue execution of the middleware pipeline.
|
|
|
+ *
|
|
|
+ * @note Should be called from middlewares if you want the pipeline to continue.
|
|
|
+ *
|
|
|
+ * @param request
|
|
|
+ * @return response
|
|
|
+ */
|
|
|
+ http::Response next(const http::Request &request);
|
|
|
+
|
|
|
/**
|
|
|
* @brief Controller for the web service.
|
|
|
*
|
|
|
- * Pass derived classes to WebService::attach().
|
|
|
+ * Pass derived classes to WebService::controller().
|
|
|
*/
|
|
|
class Controller {
|
|
|
friend class WebService;
|
|
@@ -93,8 +117,8 @@ namespace kbf {
|
|
|
* @param request
|
|
|
* @return HTTP response
|
|
|
*/
|
|
|
- virtual kbf::http::Response get(const kbf::http::Request &request) {
|
|
|
- return kbf::http::Response("method not allowed", 405);
|
|
|
+ virtual http::Response get(const http::Request &request) {
|
|
|
+ return http::Response("method not allowed", 405);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -103,8 +127,8 @@ namespace kbf {
|
|
|
* @param request
|
|
|
* @return HTTP response
|
|
|
*/
|
|
|
- virtual kbf::http::Response post(const kbf::http::Request &request) {
|
|
|
- return kbf::http::Response("method not allowed", 405);
|
|
|
+ virtual http::Response post(const http::Request &request) {
|
|
|
+ return http::Response("method not allowed", 405);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -112,21 +136,59 @@ namespace kbf {
|
|
|
*
|
|
|
* @param response
|
|
|
*/
|
|
|
- virtual void onResponseSent(const kbf::http::Response &response) {}
|
|
|
+ virtual void onResponseSent(const http::Response &response) {}
|
|
|
|
|
|
private:
|
|
|
- static void responseSentHandler(const kbf::http::Response &response, void *data);
|
|
|
+ static void responseSentHandler(const http::Response &response, void *data);
|
|
|
};
|
|
|
|
|
|
- private:
|
|
|
- kbf::http::Server server;
|
|
|
-
|
|
|
- static kbf::http::Response handleGet(const kbf::http::Request &request, void *data);
|
|
|
+ /**
|
|
|
+ * @brief Base class for HTTP middlewares.
|
|
|
+ *
|
|
|
+ * Pass derived classes to #WebService::middleware().
|
|
|
+ *
|
|
|
+ * The #run() method will be called for every request. Implementations should call webService->next() for
|
|
|
+ * the pipeline to continue.
|
|
|
+ *
|
|
|
+ * @note If multiple middlewares are added to a WebService, they will be called in the order they were added.
|
|
|
+ */
|
|
|
+ class Middleware {
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * @brief Function to run for every request. Should call webService->next() for the pipeline to continue.
|
|
|
+ *
|
|
|
+ * @param request incoming request
|
|
|
+ * @param webService webService instance
|
|
|
+ * @return response
|
|
|
+ */
|
|
|
+ virtual http::Response run(const http::Request &request, WebService &webService) = 0;
|
|
|
+ };
|
|
|
|
|
|
- static kbf::http::Response handlePost(const kbf::http::Request &request, void *data);
|
|
|
+ private:
|
|
|
+ http::Server server;
|
|
|
|
|
|
bool running = false;
|
|
|
int port;
|
|
|
+
|
|
|
+ struct HandlerArg {
|
|
|
+ WebService &webService;
|
|
|
+ Controller &controller;
|
|
|
+ };
|
|
|
+
|
|
|
+ typedef http::Response (WebService::Controller::*MethodFunction)(const http::Request &request);
|
|
|
+
|
|
|
+ MethodFunction currentMethod = nullptr;
|
|
|
+ Controller *currentController = nullptr;
|
|
|
+
|
|
|
+ static http::Response handleGet(const http::Request &request, void *data);
|
|
|
+
|
|
|
+ static http::Response handlePost(const http::Request &request, void *data);
|
|
|
+
|
|
|
+ http::Response startPipeline(const http::Request &request, HandlerArg *arg);
|
|
|
+
|
|
|
+ std::vector<Middleware *> middlewares;
|
|
|
+ std::optional<std::vector<Middleware *>::iterator>
|
|
|
+ middlewareIt = std::nullopt;
|
|
|
};
|
|
|
}
|
|
|
|