/* This file is part of Flowee
*
* Copyright (C) 2017 Nathan Osman
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library 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
* Library General Public License for more details.
*
* For the full copy of the License see
*/
#ifndef HTTPENGINE_HANDLER_H
#define HTTPENGINE_HANDLER_H
#include
#include "httpengine_export.h"
class QRegExp;
namespace HttpEngine
{
class Middleware;
class Socket;
class HTTPENGINE_EXPORT HandlerPrivate;
/**
* @brief Base class for HTTP handlers
*
* When a request is received by a [Server](@ref HttpEngine::Server), it
* invokes the route() method of the root handler which is used to determine
* what happens to the request. All HTTP handlers derive from this class and
* should override the protected process() method in order to process the
* request. Each handler also maintains a list of redirects and sub-handlers
* which are used in place of invoking process() when one of the patterns
* match.
*
* To add a redirect, use the addRedirect() method. The first parameter is a
* QRegExp pattern that the request path will be tested against. If it
* matches, an HTTP 302 redirect will be written to the socket and the request
* closed. For example, to have the root path "/" redirect to "/index.html":
*
* @code
* HttpEngine::Handler handler;
* handler.addRedirect(QRegExp("^$"), "/index.html");
* @endcode
*
* To add a sub-handler, use the addSubHandler() method. Again, the first
* parameter is a QRegExp pattern. If the pattern matches, the portion of the
* path that matched the pattern is removed from the path and it is passed to
* the sub-handler's route() method. For example, to have a sub-handler
* invoked when the path begins with "/api/":
*
* @code
* HttpEngine::Handler handler, subHandler;
* handler.addSubHandler(QRegExp("^api/"), &subHandler);
* @endcode
*
* If the request doesn't match any redirect or sub-handler patterns, it is
* passed along to the process() method, which is expected to either process
* the request or write an error to the socket. The default implementation of
* process() simply returns an HTTP 404 error.
*/
class HTTPENGINE_EXPORT Handler : public QObject
{
Q_OBJECT
public:
/**
* @brief Base constructor for a handler
*/
explicit Handler(QObject *parent = nullptr);
/**
* @brief Add middleware to the handler
*/
void addMiddleware(Middleware *middleware);
/**
* @brief Add a redirect for a specific pattern
*
* The pattern and path will be added to an internal list that will be
* used when the route() method is invoked to determine whether the
* request matches any patterns. The order of the list is preserved.
*
* The destination path may use "%1", "%2", etc. to refer to captured
* parts of the pattern. The client will receive an HTTP 302 redirect.
*/
void addRedirect(const QRegExp &pattern, const QString &path);
/**
* @brief Add a handler for a specific pattern
*
* The pattern and handler will be added to an internal list that will be
* used when the route() method is invoked to determine whether the
* request matches any patterns. The order of the list is preserved.
*/
void addSubHandler(const QRegExp &pattern, Handler *handler);
/**
* @brief Route an incoming request
*/
void route(Socket *socket, const QString &path);
protected:
/**
* @brief Process a request
*
* This method should process the request either by fulfilling it, sending
* a redirect with
* [Socket::writeRedirect()](@ref HttpEngine::Socket::writeRedirect), or
* writing an error to the socket using
* [Socket::writeError()](@ref HttpEngine::Socket::writeError).
*/
virtual void process(Socket *socket, const QString &path);
private:
HandlerPrivate *const d;
friend class HandlerPrivate;
};
}
#endif