1 /* 2 * Copyright (c) 2017 Nathan Osman 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to 6 * deal in the Software without restriction, including without limitation the 7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 * sell copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 19 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 20 * IN THE SOFTWARE. 21 */ 22 23 #ifndef QHTTPENGINE_HANDLER_H 24 #define QHTTPENGINE_HANDLER_H 25 26 #include <QObject> 27 28 #include "qhttpengine_export.h" 29 30 class QRegExp; 31 32 namespace QHttpEngine 33 { 34 35 class Middleware; 36 class Socket; 37 38 class QHTTPENGINE_EXPORT HandlerPrivate; 39 40 /** 41 * @brief Base class for HTTP handlers 42 * 43 * When a request is received by a [Server](@ref QHttpEngine::Server), it 44 * invokes the route() method of the root handler which is used to determine 45 * what happens to the request. All HTTP handlers derive from this class and 46 * should override the protected process() method in order to process the 47 * request. Each handler also maintains a list of redirects and sub-handlers 48 * which are used in place of invoking process() when one of the patterns 49 * match. 50 * 51 * To add a redirect, use the addRedirect() method. The first parameter is a 52 * QRegExp pattern that the request path will be tested against. If it 53 * matches, an HTTP 302 redirect will be written to the socket and the request 54 * closed. For example, to have the root path "/" redirect to "/index.html": 55 * 56 * @code 57 * QHttpEngine::Handler handler; 58 * handler.addRedirect(QRegExp("^$"), "/index.html"); 59 * @endcode 60 * 61 * To add a sub-handler, use the addSubHandler() method. Again, the first 62 * parameter is a QRegExp pattern. If the pattern matches, the portion of the 63 * path that matched the pattern is removed from the path and it is passed to 64 * the sub-handler's route() method. For example, to have a sub-handler 65 * invoked when the path begins with "/api/": 66 * 67 * @code 68 * QHttpEngine::Handler handler, subHandler; 69 * handler.addSubHandler(QRegExp("^api/"), &subHandler); 70 * @endcode 71 * 72 * If the request doesn't match any redirect or sub-handler patterns, it is 73 * passed along to the process() method, which is expected to either process 74 * the request or write an error to the socket. The default implementation of 75 * process() simply returns an HTTP 404 error. 76 */ 77 class QHTTPENGINE_EXPORT Handler : public QObject 78 { 79 Q_OBJECT 80 81 public: 82 83 /** 84 * @brief Base constructor for a handler 85 */ 86 explicit Handler(QObject *parent = 0); 87 88 /** 89 * @brief Add middleware to the handler 90 */ 91 void addMiddleware(Middleware *middleware); 92 93 /** 94 * @brief Add a redirect for a specific pattern 95 * 96 * The pattern and path will be added to an internal list that will be 97 * used when the route() method is invoked to determine whether the 98 * request matches any patterns. The order of the list is preserved. 99 * 100 * The destination path may use "%1", "%2", etc. to refer to captured 101 * parts of the pattern. The client will receive an HTTP 302 redirect. 102 */ 103 void addRedirect(const QRegExp &pattern, const QString &path); 104 105 /** 106 * @brief Add a handler for a specific pattern 107 * 108 * The pattern and handler will be added to an internal list that will be 109 * used when the route() method is invoked to determine whether the 110 * request matches any patterns. The order of the list is preserved. 111 */ 112 void addSubHandler(const QRegExp &pattern, Handler *handler); 113 114 /** 115 * @brief Route an incoming request 116 */ 117 void route(Socket *socket, const QString &path); 118 119 protected: 120 121 /** 122 * @brief Process a request 123 * 124 * This method should process the request either by fulfilling it, sending 125 * a redirect with 126 * [Socket::writeRedirect()](@ref QHttpEngine::Socket::writeRedirect), or 127 * writing an error to the socket using 128 * [Socket::writeError()](@ref QHttpEngine::Socket::writeError). 129 */ 130 virtual void process(Socket *socket, const QString &path); 131 132 private: 133 134 HandlerPrivate *const d; 135 friend class HandlerPrivate; 136 }; 137 138 } 139 140 #endif // QHTTPENGINE_HANDLER_H 141