This commit is contained in:
2021-05-26 04:15:57 -04:00
parent 0ae56e062c
commit 75f1a4d1c3
74 changed files with 5086 additions and 42 deletions
@@ -0,0 +1,97 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QABSTRACTHTTPSERVER_H
#define QABSTRACTHTTPSERVER_H
#include <QtCore/qobject.h>
#include <QtHttpServer/qthttpserverglobal.h>
#include <QtNetwork/qhostaddress.h>
#if QT_CONFIG(ssl)
#include <QtSslServer/qsslserver.h>
#include <QSslCertificate>
#include <QSslKey>
#endif
QT_BEGIN_NAMESPACE
class QHttpServerRequest;
class QHttpServerResponder;
class QTcpServer;
class QTcpSocket;
class QWebSocket;
class QAbstractHttpServerPrivate;
class Q_HTTPSERVER_EXPORT QAbstractHttpServer : public QObject
{
Q_OBJECT
public:
QAbstractHttpServer(QObject *parent = nullptr);
quint16 listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
QVector<quint16> serverPorts();
void bind(QTcpServer *server = nullptr);
QVector<QTcpServer *> servers() const;
#if QT_CONFIG(ssl)
void sslSetup(const QSslCertificate &certificate, const QSslKey &privateKey,
QSsl::SslProtocol protocol = QSsl::SecureProtocols);
void sslSetup(const QSslConfiguration &sslConfiguration);
#endif
Q_SIGNALS:
void missingHandler(const QHttpServerRequest &request, QTcpSocket *socket);
#if defined(QT_WEBSOCKETS_LIB)
void newWebSocketConnection();
public:
bool hasPendingWebSocketConnections() const;
QWebSocket *nextPendingWebSocketConnection();
#endif // defined(QT_WEBSOCKETS_LIB)
protected:
QAbstractHttpServer(QAbstractHttpServerPrivate &dd, QObject *parent = nullptr);
virtual bool handleRequest(const QHttpServerRequest &request, QTcpSocket *socket) = 0;
static QHttpServerResponder makeResponder(const QHttpServerRequest &request,
QTcpSocket *socket);
private:
Q_DECLARE_PRIVATE(QAbstractHttpServer)
};
QT_END_NAMESPACE
#endif // QABSTRACTHTTPSERVER_H
@@ -0,0 +1,82 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QABSTRACTHTTPSERVER_P_H
#define QABSTRACTHTTPSERVER_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of QHttpServer. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
#include <QtHttpServer/qabstracthttpserver.h>
#include <QtHttpServer/qthttpserverglobal.h>
#include <private/qobject_p.h>
#if defined(QT_WEBSOCKETS_LIB)
#include <QtWebSockets/qwebsocketserver.h>
#endif // defined(QT_WEBSOCKETS_LIB)
QT_BEGIN_NAMESPACE
class QHttpServerRequest;
class Q_HTTPSERVER_EXPORT QAbstractHttpServerPrivate: public QObjectPrivate
{
Q_DECLARE_PUBLIC(QAbstractHttpServer)
public:
QAbstractHttpServerPrivate();
#if defined(QT_WEBSOCKETS_LIB)
QWebSocketServer websocketServer {
QLatin1String("QtHttpServer"),
QWebSocketServer::NonSecureMode
};
#endif // defined(QT_WEBSOCKETS_LIB)
void handleNewConnections();
void handleReadyRead(QTcpSocket *socket,
QHttpServerRequest *request);
#if QT_CONFIG(ssl)
QSslConfiguration sslConfiguration;
bool sslEnabled = false;
#endif
};
QT_END_NAMESPACE
#endif // QABSTRACTHTTPSERVER_P_H
@@ -0,0 +1,222 @@
/****************************************************************************
**
** Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVER_H
#define QHTTPSERVER_H
#include <QtHttpServer/qabstracthttpserver.h>
#include <QtHttpServer/qhttpserverrouter.h>
#include <QtHttpServer/qhttpserverrouterrule.h>
#include <QtHttpServer/qhttpserverresponse.h>
#include <QtHttpServer/qhttpserverrouterviewtraits.h>
#include <QtHttpServer/qhttpserverviewtraits.h>
#include <tuple>
QT_BEGIN_NAMESPACE
class QTcpSocket;
class QHttpServerRequest;
class QHttpServerPrivate;
class Q_HTTPSERVER_EXPORT QHttpServer final : public QAbstractHttpServer
{
Q_OBJECT
Q_DECLARE_PRIVATE(QHttpServer)
template<int I, typename ... Ts>
struct VariadicTypeAt { using Type = typename std::tuple_element<I, std::tuple<Ts...>>::type; };
template<typename ... Ts>
struct VariadicTypeLast {
using Type = typename VariadicTypeAt<sizeof ... (Ts) - 1, Ts...>::Type;
};
template<typename T>
using ResponseType =
typename std::conditional<
std::is_base_of<QHttpServerResponse, T>::value,
T,
QHttpServerResponse
>::type;
public:
explicit QHttpServer(QObject *parent = nullptr);
~QHttpServer();
QHttpServerRouter *router();
template<typename Rule = QHttpServerRouterRule, typename ... Args>
bool route(Args && ... args)
{
using ViewHandler = typename VariadicTypeLast<Args...>::Type;
using ViewTraits = QHttpServerRouterViewTraits<ViewHandler>;
static_assert(ViewTraits::Arguments::StaticAssert,
"ViewHandler arguments are in the wrong order or not supported");
return routeHelper<Rule, ViewHandler, ViewTraits>(
QtPrivate::makeIndexSequence<sizeof ... (Args) - 1>{},
std::forward<Args>(args)...);
}
template<typename ViewHandler>
void afterRequest(ViewHandler &&viewHandler)
{
using ViewTraits = QHttpServerAfterRequestViewTraits<ViewHandler>;
static_assert(ViewTraits::Arguments::StaticAssert,
"ViewHandler arguments are in the wrong order or not supported");
afterRequestHelper<ViewTraits, ViewHandler>(std::move(viewHandler));
}
using AfterRequestHandler =
std::function<QHttpServerResponse(QHttpServerResponse &&response,
const QHttpServerRequest &request)>;
private:
template<typename ViewTraits, typename ViewHandler>
typename std::enable_if<ViewTraits::Arguments::Last::IsRequest::Value &&
ViewTraits::Arguments::Count == 2, void>::type
afterRequestHelper(ViewHandler &&viewHandler) {
auto handler = [viewHandler](QHttpServerResponse &&resp,
const QHttpServerRequest &request) {
return std::move(viewHandler(std::move(resp), request));
};
afterRequestImpl(std::move(handler));
}
template<typename ViewTraits, typename ViewHandler>
typename std::enable_if<ViewTraits::Arguments::Last::IsResponse::Value &&
ViewTraits::Arguments::Count == 1, void>::type
afterRequestHelper(ViewHandler &&viewHandler) {
auto handler = [viewHandler](QHttpServerResponse &&resp,
const QHttpServerRequest &) {
return std::move(viewHandler(std::move(resp)));
};
afterRequestImpl(std::move(handler));
}
template<typename ViewTraits, typename ViewHandler>
typename std::enable_if<ViewTraits::Arguments::Last::IsResponse::Value &&
ViewTraits::Arguments::Count == 2, void>::type
afterRequestHelper(ViewHandler &&viewHandler) {
auto handler = [viewHandler](QHttpServerResponse &&resp,
const QHttpServerRequest &request) {
return std::move(viewHandler(request, std::move(resp)));
};
afterRequestImpl(std::move(handler));
}
void afterRequestImpl(AfterRequestHandler &&afterRequestHandler);
private:
template<typename Rule, typename ViewHandler, typename ViewTraits, int ... I, typename ... Args>
bool routeHelper(QtPrivate::IndexesList<I...>, Args &&... args)
{
return routeImpl<Rule,
ViewHandler,
ViewTraits,
typename VariadicTypeAt<I, Args...>::Type...>(std::forward<Args>(args)...);
}
template<typename Rule, typename ViewHandler, typename ViewTraits, typename ... Args>
bool routeImpl(Args &&...args, ViewHandler &&viewHandler)
{
auto routerHandler = [this, viewHandler] (
const QRegularExpressionMatch &match,
const QHttpServerRequest &request,
QTcpSocket *socket) mutable {
auto boundViewHandler = router()->bindCaptured<ViewHandler, ViewTraits>(
std::move(viewHandler), match);
responseImpl<ViewTraits>(boundViewHandler, request, socket);
};
return router()->addRule<ViewHandler, ViewTraits>(
new Rule(std::forward<Args>(args)..., std::move(routerHandler)));
}
template<typename ViewTraits, typename T>
typename std::enable_if<!ViewTraits::Arguments::Last::IsSpecial::Value, void>::type
responseImpl(T &boundViewHandler,
const QHttpServerRequest &request,
QTcpSocket *socket)
{
ResponseType<typename ViewTraits::ReturnType> response(boundViewHandler());
sendResponse(std::move(response), request, socket);
}
template<typename ViewTraits, typename T>
typename std::enable_if<ViewTraits::Arguments::Last::IsRequest::Value &&
ViewTraits::Arguments::PlaceholdersCount == 1, void>::type
responseImpl(T &boundViewHandler, const QHttpServerRequest &request, QTcpSocket *socket)
{
ResponseType<typename ViewTraits::ReturnType> response(boundViewHandler(request));
sendResponse(std::move(response), request, socket);
}
template<typename ViewTraits, typename T>
typename std::enable_if<ViewTraits::Arguments::Last::IsRequest::Value &&
ViewTraits::Arguments::PlaceholdersCount == 2, void>::type
responseImpl(T &boundViewHandler, const QHttpServerRequest &request, QTcpSocket *socket)
{
boundViewHandler(makeResponder(request, socket), request);
}
template<typename ViewTraits, typename T>
typename std::enable_if<ViewTraits::Arguments::Last::IsResponder::Value &&
ViewTraits::Arguments::PlaceholdersCount == 2, void>::type
responseImpl(T &boundViewHandler,
const QHttpServerRequest &request,
QTcpSocket *socket)
{
boundViewHandler(request, makeResponder(request, socket));
}
template<typename ViewTraits, typename T>
typename std::enable_if<ViewTraits::Arguments::Last::IsResponder::Value &&
ViewTraits::Arguments::PlaceholdersCount == 1, void>::type
responseImpl(T &boundViewHandler,
const QHttpServerRequest &request,
QTcpSocket *socket)
{
boundViewHandler(makeResponder(request, socket));
}
bool handleRequest(const QHttpServerRequest &request, QTcpSocket *socket) override final;
void sendResponse(QHttpServerResponse &&response,
const QHttpServerRequest &request,
QTcpSocket *socket);
};
QT_END_NAMESPACE
#endif // QHTTPSERVER_H
@@ -0,0 +1,69 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVER_P_H
#define QHTTPSERVER_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of QHttpServer. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
#include <private/qabstracthttpserver_p.h>
#include <QtHttpServer/qhttpserver.h>
#include <QtHttpServer/qhttpserverresponse.h>
#include <QtHttpServer/qhttpserverrequest.h>
#include <QtHttpServer/qhttpserverrouter.h>
#include <QtCore/qglobal.h>
#include <list>
QT_BEGIN_NAMESPACE
class QHttpServerPrivate: public QAbstractHttpServerPrivate
{
Q_DECLARE_PUBLIC(QHttpServer)
public:
QHttpServerPrivate() = default;
QHttpServerRouter router;
std::list<QHttpServer::AfterRequestHandler> afterRequestHandlers;
};
QT_END_NAMESPACE
#endif // QHTTPSERVER_P_H
@@ -0,0 +1,162 @@
/****************************************************************************
**
** Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERFUTURERESPONSE_H
#define QHTTPSERVERFUTURERESPONSE_H
#include <QtHttpServer/qhttpserverresponse.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qfuture.h>
#include <QtConcurrent>
#include <mutex>
QT_BEGIN_NAMESPACE
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
template <>
class QFutureInterface<QHttpServerResponse> : public QFutureInterfaceBase
{
public:
QFutureInterface(State initialState = NoState)
: QFutureInterfaceBase(initialState)
{
refT();
}
QFutureInterface(const QFutureInterface &other)
: QFutureInterfaceBase(other)
{
refT();
}
~QFutureInterface()
{
if (!derefT())
resultStoreBase().template clear<QHttpServerResponse>();
}
static QFutureInterface canceledResult()
{ return QFutureInterface(State(Started | Finished | Canceled)); }
QFutureInterface &operator=(const QFutureInterface &other)
{
other.refT();
if (!derefT())
resultStoreBase().template clear<QHttpServerResponse>();
QFutureInterfaceBase::operator=(other);
return *this;
}
inline QFuture<QHttpServerResponse> future()
{
return QFuture<QHttpServerResponse>(this);
}
void reportAndMoveResult(QHttpServerResponse &&result, int index = -1)
{
#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0)
std::lock_guard<QMutex> locker{*mutex()};
#else
std::lock_guard<QMutex> locker{mutex(0)};
#endif
if (queryState(Canceled) || queryState(Finished))
return;
QtPrivate::ResultStoreBase &store = resultStoreBase();
const int oldResultCount = store.count();
const int insertIndex = store.addResult(
index, static_cast<void *>(new QHttpServerResponse(std::move_if_noexcept(result))));
if (!store.filterMode() || oldResultCount < store.count()) // Let's make sure it's not in pending results.
reportResultsReady(insertIndex, store.count());
}
void reportFinished()
{
QFutureInterfaceBase::reportFinished();
}
QHttpServerResponse takeResult();
};
#endif // QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
namespace QtConcurrent {
template <>
class RunFunctionTask<QHttpServerResponse> : public RunFunctionTaskBase<QHttpServerResponse>
{
public:
void run() override
{
if (this->isCanceled()) {
this->reportFinished();
return;
}
#ifndef QT_NO_EXCEPTIONS
try {
#endif
this->runFunctor();
#ifndef QT_NO_EXCEPTIONS
} catch (QException &e) {
QFutureInterface<QHttpServerResponse>::reportException(e);
} catch (...) {
QFutureInterface<QHttpServerResponse>::reportException(QUnhandledException());
}
#endif
this->reportAndMoveResult(std::move_if_noexcept(result));
this->reportFinished();
}
QHttpServerResponse result{QHttpServerResponse::StatusCode::NotFound};
};
}
class QHttpServerFutureResponsePrivate;
class Q_HTTPSERVER_EXPORT QHttpServerFutureResponse : public QHttpServerResponse
{
Q_DECLARE_PRIVATE(QHttpServerFutureResponse)
public:
using QHttpServerResponse::QHttpServerResponse;
QHttpServerFutureResponse(const QFuture<QHttpServerResponse> &futureResponse);
virtual void write(QHttpServerResponder &&responder) const override;
protected:
QHttpServerFutureResponse(QHttpServerFutureResponsePrivate *d);
};
QT_END_NAMESPACE
#endif // QHTTPSERVERFUTURERESPONSE_H
@@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (C) 2019 Mikhail Svetkin <mikhail.svetkin@gmail.com>
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERLITERALS_P_H
#define QHTTPSERVERLITERALS_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of QHttpServer. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
#include <QtHttpServer/qthttpserverglobal.h>
#include <QtCore/qbytearray.h>
QT_BEGIN_NAMESPACE
class Q_HTTPSERVER_EXPORT QHttpServerLiterals
{
public:
static QByteArray contentTypeHeader();
static QByteArray contentTypeXEmpty();
static QByteArray contentTypeTextHtml();
static QByteArray contentTypeJson();
static QByteArray contentLengthHeader();
};
QT_END_NAMESPACE
#endif // QHTTPSERVERLITERALS_P_H
@@ -0,0 +1,108 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERREQUEST_H
#define QHTTPSERVERREQUEST_H
#include <QtHttpServer/qthttpserverglobal.h>
#include <QtCore/qdebug.h>
#include <QtCore/qglobal.h>
#include <QtCore/qurl.h>
#include <QtCore/qurlquery.h>
#include <QtNetwork/qhostaddress.h>
QT_BEGIN_NAMESPACE
class QRegularExpression;
class QString;
class QTcpSocket;
class QHttpServerRequestPrivate;
class Q_HTTPSERVER_EXPORT QHttpServerRequest
{
friend class QAbstractHttpServerPrivate;
friend class QHttpServerResponse;
Q_GADGET
public:
virtual ~QHttpServerRequest();
enum class Method
{
Unknown = 0x0000,
Get = 0x0001,
Put = 0x0002,
Delete = 0x0004,
Post = 0x0008,
Head = 0x0010,
Options = 0x0020,
Patch = 0x0040,
Connect = 0x0080,
All = Get | Put | Delete | Post | Head | Options | Patch | Connect,
// Include upper-case aliases for the sake of parsing from strings:
GET = Get,
PUT = Put,
DELETE = Delete,
POST = Post,
HEAD = Head,
OPTIONS = Options,
PATCH = Patch,
CONNECT = Connect
};
Q_ENUM(Method)
Q_DECLARE_FLAGS(Methods, Method)
Q_FLAG(Methods)
QByteArray value(const QByteArray &key) const;
QUrl url() const;
QUrlQuery query() const;
Method method() const;
QVariantMap headers() const;
QByteArray body() const;
QHostAddress remoteAddress() const;
private:
Q_DISABLE_COPY(QHttpServerRequest)
#if !defined(QT_NO_DEBUG_STREAM)
friend Q_HTTPSERVER_EXPORT QDebug operator<<(QDebug debug, const QHttpServerRequest &request);
#endif
explicit QHttpServerRequest(const QHostAddress &remoteAddress);
QScopedPointer<QHttpServerRequestPrivate> d;
};
QT_END_NAMESPACE
#endif // QHTTPSERVERREQUEST_H
@@ -0,0 +1,113 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERREQUEST_P_H
#define QHTTPSERVERREQUEST_P_H
#include <QtHttpServer/qhttpserverrequest.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qpair.h>
#include <QtCore/qregularexpression.h>
#include <QtCore/qshareddata.h>
#include <QtCore/qstring.h>
#include <QtCore/qurl.h>
#include <QtNetwork/qhostaddress.h>
#include "../3rdparty/http-parser/http_parser.h"
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of QHttpServer. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
QT_BEGIN_NAMESPACE
class QHttpServerRequestPrivate : public QSharedData
{
public:
QHttpServerRequestPrivate(const QHostAddress &remoteAddress);
quint16 port = 0;
enum class State {
NotStarted,
OnMessageBegin,
OnUrl,
OnStatus,
OnHeaders,
OnHeadersComplete,
OnBody,
OnMessageComplete,
OnChunkHeader,
OnChunkComplete
} state = State::NotStarted;
QByteArray body;
QUrl url;
http_parser httpParser;
QByteArray header(const QByteArray &key) const;
bool parse(QIODevice *socket);
QByteArray lastHeader;
QMap<uint, QPair<QByteArray, QByteArray>> headers;
const uint headersSeed = uint(qGlobalQHashSeed());
uint headerHash(const QByteArray &key) const;
void clear();
QHostAddress remoteAddress;
bool handling{false};
private:
static http_parser_settings httpParserSettings;
static bool parseUrl(const char *at, size_t length, bool connect, QUrl *url);
static QHttpServerRequestPrivate *instance(http_parser *httpParser);
static int onMessageBegin(http_parser *httpParser);
static int onUrl(http_parser *httpParser, const char *at, size_t length);
static int onStatus(http_parser *httpParser, const char *at, size_t length);
static int onHeaderField(http_parser *httpParser, const char *at, size_t length);
static int onHeaderValue(http_parser *httpParser, const char *at, size_t length);
static int onHeadersComplete(http_parser *httpParser);
static int onBody(http_parser *httpParser, const char *at, size_t length);
static int onMessageComplete(http_parser *httpParser);
static int onChunkHeader(http_parser *httpParser);
static int onChunkComplete(http_parser *httpParser);
};
QT_END_NAMESPACE
#endif // QHTTPSERVERREQUEST_P_H
@@ -0,0 +1,187 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERRESPONDER_H
#define QHTTPSERVERRESPONDER_H
#include <QtHttpServer/qthttpserverglobal.h>
#include <QtCore/qdebug.h>
#include <QtCore/qpair.h>
#include <QtCore/qglobal.h>
#include <QtCore/qstring.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qmimetype.h>
#include <utility>
#include <initializer_list>
QT_BEGIN_NAMESPACE
class QTcpSocket;
class QHttpServerRequest;
class QHttpServerResponderPrivate;
class Q_HTTPSERVER_EXPORT QHttpServerResponder final
{
Q_DECLARE_PRIVATE(QHttpServerResponder)
friend class QAbstractHttpServer;
public:
enum class StatusCode {
// 1xx: Informational
Continue = 100,
SwitchingProtocols,
Processing,
// 2xx: Success
Ok = 200,
Created,
Accepted,
NonAuthoritativeInformation,
NoContent,
ResetContent,
PartialContent,
MultiStatus,
AlreadyReported,
IMUsed = 226,
// 3xx: Redirection
MultipleChoices = 300,
MovedPermanently,
Found,
SeeOther,
NotModified,
UseProxy,
// 306: not used, was proposed as "Switch Proxy" but never standardized
TemporaryRedirect = 307,
PermanentRedirect,
// 4xx: Client Error
BadRequest = 400,
Unauthorized,
PaymentRequired,
Forbidden,
NotFound,
MethodNotAllowed,
NotAcceptable,
ProxyAuthenticationRequired,
RequestTimeout,
Conflict,
Gone,
LengthRequired,
PreconditionFailed,
PayloadTooLarge,
UriTooLong,
UnsupportedMediaType,
RequestRangeNotSatisfiable,
ExpectationFailed,
ImATeapot,
MisdirectedRequest = 421,
UnprocessableEntity,
Locked,
FailedDependency,
UpgradeRequired = 426,
PreconditionRequired = 428,
TooManyRequests,
RequestHeaderFieldsTooLarge = 431,
UnavailableForLegalReasons = 451,
// 5xx: Server Error
InternalServerError = 500,
NotImplemented,
BadGateway,
ServiceUnavailable,
GatewayTimeout,
HttpVersionNotSupported,
VariantAlsoNegotiates,
InsufficientStorage,
LoopDetected,
NotExtended = 510,
NetworkAuthenticationRequired,
NetworkConnectTimeoutError = 599,
};
using HeaderList = std::initializer_list<std::pair<QByteArray, QByteArray>>;
QHttpServerResponder(QHttpServerResponder &&other);
~QHttpServerResponder();
void write(QIODevice *data,
HeaderList headers,
StatusCode status = StatusCode::Ok);
void write(QIODevice *data,
const QByteArray &mimeType,
StatusCode status = StatusCode::Ok);
void write(const QJsonDocument &document,
HeaderList headers,
StatusCode status = StatusCode::Ok);
void write(const QJsonDocument &document,
StatusCode status = StatusCode::Ok);
void write(const QByteArray &data,
HeaderList headers,
StatusCode status = StatusCode::Ok);
void write(const QByteArray &data,
const QByteArray &mimeType,
StatusCode status = StatusCode::Ok);
void write(HeaderList headers, StatusCode status = StatusCode::Ok);
void write(StatusCode status = StatusCode::Ok);
void writeStatusLine(StatusCode status = StatusCode::Ok,
const QPair<quint8, quint8> &version = qMakePair(1u, 1u));
void writeHeader(const QByteArray &key, const QByteArray &value);
void writeHeaders(HeaderList headers);
void writeBody(const char *body, qint64 size);
void writeBody(const char *body);
void writeBody(const QByteArray &body);
QTcpSocket *socket() const;
private:
QHttpServerResponder(const QHttpServerRequest &request, QTcpSocket *socket);
QScopedPointer<QHttpServerResponderPrivate> d_ptr;
};
QT_END_NAMESPACE
Q_DECLARE_METATYPE(QHttpServerResponder::StatusCode)
#endif // QHTTPSERVERRESPONDER_H
@@ -0,0 +1,73 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERRESPONDER_P_H
#define QHTTPSERVERRESPONDER_P_H
#include <QtHttpServer/qthttpserverglobal.h>
#include <QtHttpServer/qhttpserverrequest.h>
#include <QtHttpServer/qhttpserverresponder.h>
#include <QtCore/qcoreapplication.h>
#include <QtCore/qpair.h>
#include <QtCore/qpointer.h>
#include <QtCore/qsysinfo.h>
#include <type_traits>
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of QHttpServer. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
QT_BEGIN_NAMESPACE
class QHttpServerResponderPrivate
{
public:
QHttpServerResponderPrivate(const QHttpServerRequest &request, QTcpSocket *const socket)
: request(request), socket(socket) {}
const QHttpServerRequest &request;
#if defined(QT_DEBUG)
const QPointer<QTcpSocket> socket;
#else
QTcpSocket *const socket;
#endif
bool bodyStarted{false};
};
QT_END_NAMESPACE
#endif // QHTTPSERVERRESPONDER_P_H
@@ -0,0 +1,129 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERRESPONSE_H
#define QHTTPSERVERRESPONSE_H
#include <QtHttpServer/qhttpserverresponder.h>
#include <QtCore/qscopedpointer.h>
QT_BEGIN_NAMESPACE
class QJsonObject;
class QHttpServerResponsePrivate;
class Q_HTTPSERVER_EXPORT QHttpServerResponse
{
Q_DECLARE_PRIVATE(QHttpServerResponse)
public:
using StatusCode = QHttpServerResponder::StatusCode;
QHttpServerResponse() = delete;
QHttpServerResponse(const QHttpServerResponse &other) = delete;
QHttpServerResponse& operator=(const QHttpServerResponse &other) = delete;
QHttpServerResponse(QHttpServerResponse &&other) noexcept;
QHttpServerResponse& operator=(QHttpServerResponse &&other) noexcept;
QHttpServerResponse(const StatusCode statusCode);
QHttpServerResponse(const char *data);
QHttpServerResponse(const QString &data);
explicit QHttpServerResponse(const QByteArray &data);
explicit QHttpServerResponse(QByteArray &&data);
QHttpServerResponse(const QJsonObject &data);
QHttpServerResponse(const QJsonArray &data);
QHttpServerResponse(const QByteArray &mimeType,
const QByteArray &data,
const StatusCode status = StatusCode::Ok);
QHttpServerResponse(QByteArray &&mimeType,
const QByteArray &data,
const StatusCode status = StatusCode::Ok);
QHttpServerResponse(const QByteArray &mimeType,
QByteArray &&data,
const StatusCode status = StatusCode::Ok);
QHttpServerResponse(QByteArray &&mimeType,
QByteArray &&data,
const StatusCode status = StatusCode::Ok);
virtual ~QHttpServerResponse();
static QHttpServerResponse fromFile(const QString &fileName);
QByteArray data() const;
QByteArray mimeType() const;
StatusCode statusCode() const;
void addHeader(QByteArray &&name, QByteArray &&value);
void addHeader(QByteArray &&name, const QByteArray &value);
void addHeader(const QByteArray &name, QByteArray &&value);
void addHeader(const QByteArray &name, const QByteArray &value);
void addHeaders(QHttpServerResponder::HeaderList headers);
template<typename Container>
void addHeaders(const Container &headerList)
{
for (const auto &header : headerList)
addHeader(header.first, header.second);
}
void clearHeader(const QByteArray &name);
void clearHeaders();
void setHeader(QByteArray &&name, QByteArray &&value);
void setHeader(QByteArray &&name, const QByteArray &value);
void setHeader(const QByteArray &name, QByteArray &&value);
void setHeader(const QByteArray &name, const QByteArray &value);
void setHeaders(QHttpServerResponder::HeaderList headers);
bool hasHeader(const QByteArray &name) const;
bool hasHeader(const QByteArray &name, const QByteArray &value) const;
QVector<QByteArray> headers(const QByteArray &name) const;
virtual void write(QHttpServerResponder &&responder) const;
protected:
QHttpServerResponse(QHttpServerResponsePrivate *d);
QScopedPointer<QHttpServerResponsePrivate> d_ptr;
};
QT_END_NAMESPACE
#endif // QHTTPSERVERRESPONSE_H
@@ -0,0 +1,76 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERRESPONSE_P_H
#define QHTTPSERVERRESPONSE_P_H
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of QHttpServerResponse. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
#include <private/qabstracthttpserver_p.h>
#include <QtHttpServer/qhttpserverresponse.h>
#include <functional>
#include <unordered_map>
QT_BEGIN_NAMESPACE
class QHttpServerResponsePrivate
{
struct HashHelper {
std::size_t operator()(const QByteArray& key) const
{
return qHash(key.toLower());
}
};
public:
explicit QHttpServerResponsePrivate() = default;
virtual ~QHttpServerResponsePrivate() = default;
QHttpServerResponsePrivate(QByteArray &&d, const QHttpServerResponse::StatusCode sc);
QHttpServerResponsePrivate(const QHttpServerResponse::StatusCode sc);
QByteArray data;
QHttpServerResponse::StatusCode statusCode;
std::unordered_multimap<QByteArray, QByteArray, HashHelper> headers;
bool derived{false};
};
QT_END_NAMESPACE
#endif // QHTTPSERVERRESPONSE_P_H
@@ -0,0 +1,161 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERROUTER_H
#define QHTTPSERVERROUTER_H
#include <QtHttpServer/qthttpserverglobal.h>
#include <QtHttpServer/qhttpserverrouterviewtraits.h>
#include <QtCore/qscopedpointer.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qregularexpression.h>
#include <functional>
#include <initializer_list>
QT_BEGIN_NAMESPACE
namespace QtPrivate {
template<int> struct QHttpServerRouterPlaceholder {};
}
QT_END_NAMESPACE
namespace std {
template<int N>
struct is_placeholder<QT_PREPEND_NAMESPACE(QtPrivate::QHttpServerRouterPlaceholder<N>)> :
integral_constant<int , N + 1>
{};
}
QT_BEGIN_NAMESPACE
class QTcpSocket;
class QHttpServerRequest;
class QHttpServerRouterRule;
class QHttpServerRouterPrivate;
class Q_HTTPSERVER_EXPORT QHttpServerRouter
{
Q_DECLARE_PRIVATE(QHttpServerRouter)
public:
QHttpServerRouter();
~QHttpServerRouter();
template<typename Type>
bool addConverter(const QLatin1String &regexp) {
static_assert(QMetaTypeId2<Type>::Defined,
"Type is not registered with Qt's meta-object system: "
"please apply Q_DECLARE_METATYPE() to it");
if (!QMetaType::registerConverter<QString, Type>())
return false;
addConverter(qMetaTypeId<Type>(), regexp);
return true;
}
void addConverter(const int type, const QLatin1String &regexp);
void removeConverter(const int);
void clearConverters();
const QMap<int, QLatin1String> &converters() const;
static const QMap<int, QLatin1String> &defaultConverters();
template<typename ViewHandler, typename ViewTraits = QHttpServerRouterViewTraits<ViewHandler>>
bool addRule(QHttpServerRouterRule *rule)
{
return addRuleHelper<ViewTraits>(
rule,
typename ViewTraits::Arguments::Indexes{});
}
template<typename ViewHandler, typename ViewTraits = QHttpServerRouterViewTraits<ViewHandler>>
typename ViewTraits::BindableType bindCaptured(ViewHandler &&handler,
const QRegularExpressionMatch &match) const
{
return bindCapturedImpl<ViewHandler, ViewTraits>(
std::forward<ViewHandler>(handler),
match,
typename ViewTraits::Arguments::CapturableIndexes{},
typename ViewTraits::Arguments::PlaceholdersIndexes{});
}
bool handleRequest(const QHttpServerRequest &request,
QTcpSocket *socket) const;
private:
template<typename ViewTraits, int ... Idx>
bool addRuleHelper(QHttpServerRouterRule *rule,
QtPrivate::IndexesList<Idx...>)
{
const std::initializer_list<int> types = {
ViewTraits::Arguments::template metaTypeId<Idx>()...};
return addRuleImpl(rule, types);
}
bool addRuleImpl(QHttpServerRouterRule *rule,
const std::initializer_list<int> &metaTypes);
template<typename ViewHandler, typename ViewTraits, int ... Cx, int ... Px>
typename std::enable_if<ViewTraits::Arguments::CapturableCount != 0, typename ViewTraits::BindableType>::type
bindCapturedImpl(ViewHandler &&handler,
const QRegularExpressionMatch &match,
QtPrivate::IndexesList<Cx...>,
QtPrivate::IndexesList<Px...>) const
{
return std::bind(
std::forward<ViewHandler>(handler),
QVariant(match.captured(Cx + 1))
.value<typename ViewTraits::Arguments::template Arg<Cx>::CleanType>()...,
QtPrivate::QHttpServerRouterPlaceholder<Px>{}...);
}
template<typename ViewHandler, typename ViewTraits, int ... Cx, int ... Px>
typename std::enable_if<!ViewTraits::Arguments::CapturableCount, typename ViewTraits::BindableType>::type
bindCapturedImpl(ViewHandler &&handler,
const QRegularExpressionMatch &,
QtPrivate::IndexesList<Cx...>,
QtPrivate::IndexesList<Px...>) const
{
return std::bind(
std::forward<ViewHandler>(handler),
QtPrivate::QHttpServerRouterPlaceholder<Px>{}...);
}
QScopedPointer<QHttpServerRouterPrivate> d_ptr;
};
QT_END_NAMESPACE
#endif // QHTTPSERVERROUTER_H
@@ -0,0 +1,65 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERROUTER_P_H
#define QHTTPSERVERROUTER_P_H
#include <QtHttpServer/qhttpserverrouter.h>
#include <QtHttpServer/qhttpserverrouterrule.h>
#include <QtCore/qmap.h>
#include <QtCore/qlist.h>
#include <QtCore/qstring.h>
#include <memory>
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of QHttpServer. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
QT_BEGIN_NAMESPACE
class QHttpServerRouterPrivate
{
public:
QHttpServerRouterPrivate();
QMap<int, QLatin1String> converters;
std::list<std::unique_ptr<QHttpServerRouterRule>> rules;
};
QT_END_NAMESPACE
#endif // QHTTPSERVERROUTER_P_H
@@ -0,0 +1,90 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERROUTERRULE_H
#define QHTTPSERVERROUTERRULE_H
#include <QtHttpServer/qhttpserverrequest.h>
#include <QtCore/qmap.h>
QT_BEGIN_NAMESPACE
class QString;
class QHttpServerRequest;
class QTcpSocket;
class QRegularExpressionMatch;
class QHttpServerRouter;
class QHttpServerRouterRulePrivate;
class Q_HTTPSERVER_EXPORT QHttpServerRouterRule
{
Q_DECLARE_PRIVATE(QHttpServerRouterRule)
public:
using RouterHandler = std::function<void(const QRegularExpressionMatch &,
const QHttpServerRequest &,
QTcpSocket *)>;
explicit QHttpServerRouterRule(const QString &pathPattern, RouterHandler &&routerHandler);
explicit QHttpServerRouterRule(const QString &pathPattern,
const QHttpServerRequest::Methods methods,
RouterHandler &&routerHandler);
explicit QHttpServerRouterRule(const QString &pathPattern,
const char * methods,
RouterHandler &&routerHandler);
QHttpServerRouterRule(QHttpServerRouterRule &&other) = delete;
QHttpServerRouterRule &operator=(QHttpServerRouterRule &&other) = delete;
virtual ~QHttpServerRouterRule();
protected:
bool exec(const QHttpServerRequest &request, QTcpSocket *socket) const;
bool hasValidMethods() const;
bool createPathRegexp(const std::initializer_list<int> &metaTypes,
const QMap<int, QLatin1String> &converters);
virtual bool matches(const QHttpServerRequest &request,
QRegularExpressionMatch *match) const;
QHttpServerRouterRule(QHttpServerRouterRulePrivate *d);
private:
Q_DISABLE_COPY(QHttpServerRouterRule)
QScopedPointer<QHttpServerRouterRulePrivate> d_ptr;
friend class QHttpServerRouter;
};
QT_END_NAMESPACE
#endif // QHTTPSERVERROUTERRULE_H
@@ -0,0 +1,62 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERROUTERRULE_P_H
#define QHTTPSERVERROUTERRULE_P_H
#include <QtHttpServer/qhttpserverrouterrule.h>
#include <QtCore/qregularexpression.h>
#include <QtCore/qstring.h>
//
// W A R N I N G
// -------------
//
// This file is not part of the Qt API. It exists for the convenience
// of QHttpServer. This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
QT_BEGIN_NAMESPACE
class Q_HTTPSERVER_EXPORT QHttpServerRouterRulePrivate
{
public:
QString pathPattern;
QHttpServerRequest::Methods methods;
QHttpServerRouterRule::RouterHandler routerHandler;
QRegularExpression pathRegexp;
};
QT_END_NAMESPACE
#endif // QHTTPSERVERROUTERRULE_P_H
@@ -0,0 +1,164 @@
/****************************************************************************
**
** Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERROUTERVIEWTRAITS_H
#define QHTTPSERVERROUTERVIEWTRAITS_H
#include <QtHttpServer/qhttpserverviewtraits_impl.h>
QT_BEGIN_NAMESPACE
class QHttpServerRequest;
class QHttpServerResponder;
namespace QtPrivate {
template<typename ViewHandler, bool DisableStaticAssert>
struct RouterViewTraitsHelper : ViewTraits<ViewHandler, DisableStaticAssert> {
using VTraits = ViewTraits<ViewHandler, DisableStaticAssert>;
using FunctionTraits = typename VTraits::FTraits;
template<int I>
struct ArgumentChecker : FunctionTraits::template Arg<I> {
using IsRequest = typename VTraits::template Special<I, const QHttpServerRequest &>;
static_assert(IsRequest::AssertCondition,
"ViewHandler arguments error: "
"QHttpServerRequest can only be passed as a const reference");
using IsResponder = typename VTraits::template Special<I, QHttpServerResponder &&>;
static_assert(IsResponder::AssertCondition,
"ViewHandler arguments error: "
"QHttpServerResponder can only be passed as a universal reference");
using IsSpecial = CheckAny<IsRequest, IsResponder>;
struct IsSimple {
static constexpr bool Value = !IsSpecial::Value &&
I < FunctionTraits::ArgumentCount &&
FunctionTraits::ArgumentIndexMax != -1;
static constexpr bool Valid = FunctionTraits::template Arg<I>::Defined;
static constexpr bool StaticAssert =
DisableStaticAssert || !Value || Valid;
static_assert(StaticAssert,
"ViewHandler arguments error: "
"Type is not registered, please use the Q_DECLARE_METATYPE macro "
"to make it known to Qt's meta-object system");
};
using CheckOk = CheckAny<IsSimple, IsSpecial>;
static constexpr bool Valid = CheckOk::Valid;
static constexpr bool StaticAssert = CheckOk::StaticAssert;
};
struct Arguments {
template<int ... I>
struct ArgumentsReturn {
template<int Idx>
using Arg = ArgumentChecker<Idx>;
template<int Idx>
static constexpr int metaTypeId() noexcept
{
using Type = typename FunctionTraits::template Arg<Idx>::CleanType;
return qMetaTypeId<
typename std::conditional<
QMetaTypeId2<Type>::Defined,
Type,
void>::type>();
}
static constexpr std::size_t Count = FunctionTraits::ArgumentCount;
static constexpr std::size_t CapturableCount =
StaticMath::Sum::eval(
static_cast<std::size_t>(FunctionTraits::template Arg<I>::Defined)...);
static constexpr std::size_t PlaceholdersCount = Count - CapturableCount;
static constexpr bool Valid = StaticMath::And::eval(Arg<I>::Valid...);
static constexpr bool StaticAssert =
StaticMath::And::eval(Arg<I>::StaticAssert...);
using Indexes = typename QtPrivate::IndexesList<I...>;
using CapturableIndexes =
typename QtPrivate::Indexes<CapturableCount>::Value;
using PlaceholdersIndexes =
typename QtPrivate::Indexes<PlaceholdersCount>::Value;
using Last = Arg<FunctionTraits::ArgumentIndexMax>;
};
template<int ... I>
static constexpr ArgumentsReturn<I...> eval(QtPrivate::IndexesList<I...>) noexcept
{
return ArgumentsReturn<I...>{};
}
};
template<int CaptureOffset>
struct BindType {
template<typename ... Args>
struct FunctionWrapper {
using Type = std::function<typename FunctionTraits::ReturnType (Args...)>;
};
template<int Id>
using OffsetArg = typename FunctionTraits::template Arg<CaptureOffset + Id>::Type;
template<int ... Idx>
static constexpr typename FunctionWrapper<OffsetArg<Idx>...>::Type
eval(QtPrivate::IndexesList<Idx...>) noexcept;
};
};
} // namespace QtPrivate
template <typename ViewHandler, bool DisableStaticAssert = false>
struct QHttpServerRouterViewTraits
{
using Helpers = typename QtPrivate::RouterViewTraitsHelper<ViewHandler, DisableStaticAssert>;
using ReturnType = typename Helpers::FunctionTraits::ReturnType;
using Arguments = decltype(Helpers::Arguments::eval(typename Helpers::ArgumentIndexes{}));
using BindableType = decltype(
Helpers::template BindType<Arguments::CapturableCount>::eval(
typename Arguments::PlaceholdersIndexes{}));
};
QT_END_NAMESPACE
#endif // QHTTPSERVERROUTERVIEWTRAITS_H
@@ -0,0 +1,109 @@
/****************************************************************************
**
** Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERVIEWTRAITS_H
#define QHTTPSERVERVIEWTRAITS_H
#include <QtHttpServer/qhttpserverviewtraits_impl.h>
QT_BEGIN_NAMESPACE
class QHttpServerRequest;
class QHttpServerResponse;
namespace QtPrivate {
template <typename ViewHandler, bool DisableStaticAssert>
struct AfterRequestViewTraitsHelper : ViewTraits<ViewHandler, DisableStaticAssert> {
using VTraits = ViewTraits<ViewHandler, DisableStaticAssert>;
using FunctionTraits = typename VTraits::FTraits;
static_assert(DisableStaticAssert ||
FunctionTraits::ArgumentCount == 2 ||
FunctionTraits::ArgumentCount == 1,
"ViewHandler arguments error: "
"afterRequest can only accept QHttpServerResponse and QHttpServerRequest");
static_assert(DisableStaticAssert ||
std::is_same<typename FunctionTraits::ReturnType,
QHttpServerResponse>::value,
"ViewHandler return type error: "
"Return type can only be QHttpServerResponse");
template<int I>
struct ArgumentChecker {
using IsRequest = typename VTraits::template Special<I, const QHttpServerRequest &>;
static_assert(IsRequest::AssertCondition,
"ViewHandler arguments error: "
"QHttpServerRequest can only be passed as a const reference");
using IsResponse = typename VTraits::template Special<I, QHttpServerResponse &&>;
static_assert(IsResponse::AssertCondition,
"ViewHandler arguments error: "
"QHttpServerResponse can only be passed as a universal reference");
using IsSpecial = CheckAny<IsRequest, IsResponse>;
static constexpr bool Valid = IsSpecial::Valid;
static constexpr bool StaticAssert = IsSpecial::StaticAssert;
};
struct Arguments {
template<int ... I>
struct ArgumentsReturn {
template<int Idx>
using Arg = ArgumentChecker<Idx>;
static constexpr bool Valid = QtPrivate::StaticMath::And::eval(Arg<I>::Valid...);
static constexpr bool StaticAssert = QtPrivate::StaticMath::And::eval(
Arg<I>::StaticAssert...);
using Last = Arg<FunctionTraits::ArgumentIndexMax>;
static constexpr std::size_t Count = FunctionTraits::ArgumentCount;
};
template<int ... I>
static constexpr ArgumentsReturn<I...> eval(QtPrivate::IndexesList<I...>) noexcept
{
return ArgumentsReturn<I...>{};
}
};
};
} // namespace QtPrivate
template <typename ViewHandler, bool DisableStaticAssert = false>
struct QHttpServerAfterRequestViewTraits
{
using Helpers = typename QtPrivate::AfterRequestViewTraitsHelper<ViewHandler, DisableStaticAssert>;
using Arguments = decltype(Helpers::Arguments::eval(typename Helpers::ArgumentIndexes{}));
};
QT_END_NAMESPACE
#endif // QHTTPSERVERVIEWTRAITS_H
@@ -0,0 +1,194 @@
/****************************************************************************
**
** Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTPSERVERVIEWTRAITS_IMPL_H
#define QHTTPSERVERVIEWTRAITS_IMPL_H
#include <QtCore/qglobal.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qnamespace.h>
#include <QtCore/qobjectdefs.h>
#include <functional>
#include <tuple>
#include <type_traits>
QT_BEGIN_NAMESPACE
namespace QtPrivate {
template<typename T>
struct RemoveCVRef
{
using Type = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
};
template<bool classMember, typename ReturnT, typename ... Args>
struct FunctionTraitsHelper
{
static constexpr const int ArgumentCount = sizeof ... (Args);
static constexpr const int ArgumentIndexMax = ArgumentCount - 1;
static constexpr const bool IsClassMember = classMember;
using ReturnType = ReturnT;
template <int I>
struct Arg {
using Type = typename std::tuple_element<I, std::tuple<Args...>>::type;
using CleanType = typename QtPrivate::RemoveCVRef<Type>::Type;
static constexpr bool Defined = QMetaTypeId2<CleanType>::Defined;
};
};
template<bool classMember, typename ReturnT>
struct FunctionTraitsHelper<classMember, ReturnT>
{
static constexpr const int ArgumentCount = 0;
static constexpr const int ArgumentIndexMax = -1;
static constexpr const bool IsClassMember = classMember;
using ReturnType = ReturnT;
template <int I>
struct Arg {
using Type = std::false_type;
using CleanType = Type;
static constexpr bool Defined = QMetaTypeId2<CleanType>::Defined;
};
};
template<typename T>
struct FunctionTraits;
template<typename T>
struct FunctionTraits : public FunctionTraits<decltype(&T::operator())>{};
template<typename ReturnT, typename ... Args>
struct FunctionTraits<ReturnT (*)(Args...)>
: public FunctionTraitsHelper<false, ReturnT, Args...>
{
};
template<class ReturnT, class ClassT, class ...Args>
struct FunctionTraits<ReturnT (ClassT::*)(Args...) const>
: public FunctionTraitsHelper<true, ReturnT, Args...>
{
using classType = ClassT;
};
struct StaticMath {
template <template<typename> class Predicate, bool defaultValue>
struct Loop {
static constexpr bool eval() noexcept {
return defaultValue;
}
template<typename T, typename ... N>
static constexpr T eval(const T it, N ...n) noexcept {
return Predicate<T>::eval(it, eval(n...));
}
};
template<typename T>
struct SumPredicate {
static constexpr T eval(const T rs, const T ls) noexcept
{
return rs + ls;
}
};
template<typename T>
struct AndPredicate {
static constexpr T eval(const T rs, const T ls) noexcept
{
return rs && ls;
}
};
using Sum = Loop<SumPredicate, false>;
using And = Loop<AndPredicate, true>;
using Or = Sum;
};
template<typename ... T>
struct CheckAny {
static constexpr bool Value = StaticMath::Or::eval(T::Value...);
static constexpr bool Valid = StaticMath::Or::eval(T::Valid...);
static constexpr bool StaticAssert = StaticMath::Or::eval(T::StaticAssert...);
};
template<typename ViewHandler, bool DisableStaticAssert>
struct ViewTraits {
using FTraits = FunctionTraits<ViewHandler>;
using ArgumentIndexes = typename Indexes<FTraits::ArgumentCount>::Value;
template<int I, typename Special>
struct SpecialHelper {
using Arg = typename FTraits::template Arg<I>;
using CleanSpecialT = typename RemoveCVRef<Special>::Type;
static constexpr bool TypeMatched = std::is_same<typename Arg::CleanType, CleanSpecialT>::value;
static constexpr bool TypeCVRefMatched = std::is_same<typename Arg::Type, Special>::value;
static constexpr bool ValidPosition =
(I == FTraits::ArgumentIndexMax ||
I == FTraits::ArgumentIndexMax - 1);
static constexpr bool ValidAll = TypeCVRefMatched && ValidPosition;
static constexpr bool AssertCondition =
DisableStaticAssert || !TypeMatched || TypeCVRefMatched;
static constexpr bool AssertConditionOrder =
DisableStaticAssert || !TypeMatched || ValidPosition;
static constexpr bool StaticAssert = AssertCondition && AssertConditionOrder;
static_assert(AssertConditionOrder,
"ViewHandler arguments error: "
"QHttpServerRequest or QHttpServerResponder"
" can only be the last argument");
};
template<int I, typename T>
struct Special {
using Helper = SpecialHelper<I, T>;
static constexpr bool Value = Helper::TypeMatched;
static constexpr bool Valid = Helper::ValidAll;
static constexpr bool StaticAssert = Helper::StaticAssert;
static constexpr bool AssertCondition = Helper::AssertCondition;
};
};
} // namespace QtPrivate
QT_END_NAMESPACE
#endif // QHTTPSERVERVIEWTRAITS_IMPL_H
@@ -0,0 +1,50 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtHttpServer module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 or (at your option) any later version
** approved by the KDE Free Qt Foundation. The licenses are as published by
** the Free Software Foundation and appearing in the file LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QTHTTPSERVERGLOBAL_H
#define QTHTTPSERVERGLOBAL_H
#include <QtCore/qglobal.h>
QT_BEGIN_NAMESPACE
#ifndef QT_STATIC
# if defined(QT_BUILD_HTTPSERVER_LIB)
# define Q_HTTPSERVER_EXPORT Q_DECL_EXPORT
# else
# define Q_HTTPSERVER_EXPORT Q_DECL_IMPORT
# endif
#else
# define Q_HTTPSERVER_EXPORT
#endif
QT_END_NAMESPACE
#endif // QTHTTPSERVERGLOBAL_H