mirror of
https://github.com/QuasarApp/qthttpserver.git
synced 2025-05-12 09:29:42 +00:00
Introduce QHttpServer
QHttpServer provides a simplified interface to QAbstractHttpServer and QHttpServerRouter. Change-Id: I884204aa8140bbab4c0d6a8ab4c798e0b2470e29 Reviewed-by: Paul Wicking <paul.wicking@qt.io> Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
This commit is contained in:
parent
a856556784
commit
540daf882f
4
examples/examples.pro
Normal file
4
examples/examples.pro
Normal file
@ -0,0 +1,4 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = \
|
||||
httpserver
|
5
examples/httpserver/httpserver.pro
Normal file
5
examples/httpserver/httpserver.pro
Normal file
@ -0,0 +1,5 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = \
|
||||
simple
|
||||
|
118
examples/httpserver/simple/main.cpp
Normal file
118
examples/httpserver/simple/main.cpp
Normal file
@ -0,0 +1,118 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 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:BSD$
|
||||
** 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.
|
||||
**
|
||||
** BSD License Usage
|
||||
** Alternatively, you may use this file under the terms of the BSD license
|
||||
** as follows:
|
||||
**
|
||||
** "Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the name of The Qt Company Ltd nor the names of its
|
||||
** contributors may be used to endorse or promote products derived
|
||||
** from this software without specific prior written permission.
|
||||
**
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtCore>
|
||||
#include <QtHttpServer>
|
||||
|
||||
static inline QString host(const QHttpServerRequest &request)
|
||||
{
|
||||
return request.headers()[QStringLiteral("Host")].toString();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication app(argc, argv);
|
||||
|
||||
QHttpServer httpServer;
|
||||
httpServer.route("/", []() {
|
||||
return "Hello world";
|
||||
});
|
||||
|
||||
httpServer.route("/query", [] (const QHttpServerRequest &request) {
|
||||
return QString("%1/query/").arg(host(request));
|
||||
});
|
||||
|
||||
httpServer.route("/query/", [] (qint32 id, const QHttpServerRequest &request) {
|
||||
return QString("%1/query/%2").arg(host(request)).arg(id);
|
||||
});
|
||||
|
||||
httpServer.route("/query/<arg>/log", [] (qint32 id, const QHttpServerRequest &request) {
|
||||
return QString("%1/query/%2/log").arg(host(request)).arg(id);
|
||||
});
|
||||
|
||||
httpServer.route("/query/<arg>/log/", [] (qint32 id, float threshold,
|
||||
const QHttpServerRequest &request) {
|
||||
return QString("%1/query/%2/log/%3").arg(host(request)).arg(id).arg(threshold);
|
||||
});
|
||||
|
||||
httpServer.route("/user/", [] (const qint32 id) {
|
||||
return QString("User %1").arg(id);
|
||||
});
|
||||
|
||||
httpServer.route("/user/<arg>/detail", [] (const qint32 id) {
|
||||
return QString("User %1 detail").arg(id);
|
||||
});
|
||||
|
||||
httpServer.route("/user/<arg>/detail/", [] (const qint32 id, const qint32 year) {
|
||||
return QString("User %1 detail year - %2").arg(id).arg(year);
|
||||
});
|
||||
|
||||
httpServer.route("/json/", [] {
|
||||
return QJsonObject{
|
||||
{
|
||||
{"key1", "1"},
|
||||
{"key2", "2"},
|
||||
{"key3", "3"}
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
const auto port = httpServer.listen(QHostAddress::Any);
|
||||
if (port == -1) {
|
||||
qDebug() << QCoreApplication::translate(
|
||||
"QHttpServerExample", "Could not run on http://127.0.0.1:%1/").arg(port);
|
||||
return 0;
|
||||
}
|
||||
|
||||
qDebug() << QCoreApplication::translate(
|
||||
"QHttpServerExample", "Running on http://127.0.0.1:%1/ (Press CTRL+C to quit)").arg(port);
|
||||
|
||||
return app.exec();
|
||||
}
|
11
examples/httpserver/simple/simple.pro
Normal file
11
examples/httpserver/simple/simple.pro
Normal file
@ -0,0 +1,11 @@
|
||||
requires(qtHaveModule(httpserver))
|
||||
|
||||
TEMPLATE = app
|
||||
|
||||
QT += httpserver
|
||||
|
||||
SOURCES += \
|
||||
main.cpp
|
||||
|
||||
target.path = $$[QT_INSTALL_EXAMPLES]/httpserver/simple
|
||||
INSTALLS += target
|
@ -9,11 +9,15 @@ HEADERS += \
|
||||
qthttpserverglobal.h \
|
||||
qabstracthttpserver.h \
|
||||
qabstracthttpserver_p.h \
|
||||
qhttpserver.h \
|
||||
qhttpserver_p.h \
|
||||
qhttpserverhelpers.h \
|
||||
qhttpserverrequest.h \
|
||||
qhttpserverrequest_p.h \
|
||||
qhttpserverresponder.h \
|
||||
qhttpserverresponder_p.h \
|
||||
qhttpserverresponse.h \
|
||||
qhttpserverresponse_p.h \
|
||||
qhttpserverrouter.h \
|
||||
qhttpserverrouter_p.h \
|
||||
qhttpserverrouterrule.h \
|
||||
@ -22,8 +26,10 @@ HEADERS += \
|
||||
|
||||
SOURCES += \
|
||||
qabstracthttpserver.cpp \
|
||||
qhttpserver.cpp \
|
||||
qhttpserverrequest.cpp \
|
||||
qhttpserverresponder.cpp \
|
||||
qhttpserverresponse.cpp \
|
||||
qhttpserverrouter.cpp \
|
||||
qhttpserverrouterrule.cpp
|
||||
|
||||
|
150
src/httpserver/qhttpserver.cpp
Normal file
150
src/httpserver/qhttpserver.cpp
Normal file
@ -0,0 +1,150 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** 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 Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or 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.GPL2 and 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-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtHttpServer/qhttpserver.h>
|
||||
|
||||
|
||||
#include <QtHttpServer/qhttpserverrequest.h>
|
||||
#include <QtHttpServer/qhttpserverresponder.h>
|
||||
#include <QtHttpServer/qhttpserverresponse.h>
|
||||
|
||||
#include <private/qhttpserver_p.h>
|
||||
|
||||
#include <QtCore/qloggingcategory.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
Q_LOGGING_CATEGORY(lcHS, "qt.httpserver");
|
||||
|
||||
/*!
|
||||
\class QHttpServer
|
||||
\brief QHttpServer is a simplified API for QAbstractHttpServer and QHttpServerRouter.
|
||||
|
||||
\code
|
||||
|
||||
QHttpServer server;
|
||||
|
||||
server.route("/", [] () {
|
||||
return "hello world";
|
||||
});
|
||||
server.listen();
|
||||
|
||||
\endcode
|
||||
*/
|
||||
|
||||
QHttpServer::QHttpServer(QObject *parent)
|
||||
: QAbstractHttpServer(*new QHttpServerPrivate, parent)
|
||||
{
|
||||
connect(this, &QAbstractHttpServer::missingHandler, this,
|
||||
[=] (const QHttpServerRequest &request, QTcpSocket *socket) {
|
||||
qCDebug(lcHS) << tr("missing handler:") << request.url().path();
|
||||
sendResponse(
|
||||
QHttpServerResponse(QHttpServerResponder::StatusCode::NotFound), request, socket);
|
||||
});
|
||||
}
|
||||
|
||||
/*! \fn template<typename Rule = QHttpServerRouterRule, typename ... Args> bool route(Args && ... args)
|
||||
This function is just a wrapper to simplify the router API.
|
||||
|
||||
This function takes variadic arguments. The last argument is \c a callback (ViewHandler).
|
||||
The remaining arguments are used to create a new \a Rule (the default is QHttpServerRouterRule).
|
||||
This is in turn added to the QHttpServerRouter.
|
||||
|
||||
\c ViewHandler can only be a lambda. The lambda definition can take an optional special argument,
|
||||
either \c {const QHttpServerRequest&} or \c {QHttpServerResponder&&}.
|
||||
This special argument must be the last in the parameter list.
|
||||
|
||||
Examples:
|
||||
|
||||
\code
|
||||
|
||||
QHttpServer server;
|
||||
|
||||
// Valid:
|
||||
server.route("test", [] (const int page) { return ""; });
|
||||
server.route("test", [] (const int page, const QHttpServerRequest &request) { return ""; });
|
||||
server.route("test", [] (QHttpServerResponder &&responder) { return ""; });
|
||||
|
||||
// Invalid (compile time error):
|
||||
server.route("test", [] (const QHttpServerRequest &request, const int page) { return ""; }); // request must be last
|
||||
server.route("test", [] (QHttpServerRequest &request) { return ""; }); // request must be passed by const reference
|
||||
server.route("test", [] (QHttpServerResponder &responder) { return ""; }); // responder must be passed by universal reference
|
||||
|
||||
\endcode
|
||||
|
||||
\sa QHttpServerRouter::addRule
|
||||
*/
|
||||
|
||||
/*!
|
||||
Destroys a QHttpServer.
|
||||
*/
|
||||
QHttpServer::~QHttpServer()
|
||||
{
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns the router object.
|
||||
*/
|
||||
QHttpServerRouter *QHttpServer::router()
|
||||
{
|
||||
Q_D(QHttpServer);
|
||||
return &d->router;
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QHttpServer::sendResponse(const QHttpServerResponse &response,
|
||||
const QHttpServerRequest &request,
|
||||
QTcpSocket *socket)
|
||||
{
|
||||
auto responder = makeResponder(request, socket);
|
||||
responder.write(response.data(),
|
||||
response.mimeType(),
|
||||
response.statusCode());
|
||||
}
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
bool QHttpServer::handleRequest(const QHttpServerRequest &request, QTcpSocket *socket)
|
||||
{
|
||||
Q_D(QHttpServer);
|
||||
return d->router.handleRequest(request, socket);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
144
src/httpserver/qhttpserver.h
Normal file
144
src/httpserver/qhttpserver.h
Normal file
@ -0,0 +1,144 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 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:LGPL$
|
||||
** 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 Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or 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.GPL2 and 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-2.0.html and
|
||||
** 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 <tuple>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
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::compileCheck(),
|
||||
"ViewHandler arguments are in the wrong order or not supported");
|
||||
return routeHelper<Rule, ViewHandler, ViewTraits>(
|
||||
QtPrivate::makeIndexSequence<sizeof ... (Args) - 1>{},
|
||||
std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
return router()->addRule<ViewHandler, ViewTraits>(
|
||||
new Rule(std::forward<Args>(args)..., [this, &viewHandler] (
|
||||
QRegularExpressionMatch &match,
|
||||
const QHttpServerRequest &request,
|
||||
QTcpSocket *socket) {
|
||||
auto boundViewHandler = router()->bindCaptured<ViewHandler, ViewTraits>(
|
||||
std::forward<ViewHandler>(viewHandler), match);
|
||||
responseImpl<ViewTraits>(boundViewHandler, request, socket);
|
||||
}));
|
||||
}
|
||||
|
||||
template<typename ViewTraits, typename T>
|
||||
typename std::enable_if<ViewTraits::IsLastArgNonSpecial, void>::type
|
||||
responseImpl(T &boundViewHandler,
|
||||
const QHttpServerRequest &request,
|
||||
QTcpSocket *socket)
|
||||
{
|
||||
const QHttpServerResponse response(boundViewHandler());
|
||||
sendResponse(response, request, socket);
|
||||
}
|
||||
|
||||
template<typename ViewTraits, typename T>
|
||||
typename std::enable_if<ViewTraits::IsLastArgRequest, void>::type
|
||||
responseImpl(T &boundViewHandler, const QHttpServerRequest &request, QTcpSocket *socket)
|
||||
{
|
||||
const QHttpServerResponse response(boundViewHandler(request));
|
||||
sendResponse(response, request, socket);
|
||||
}
|
||||
|
||||
template<typename ViewTraits, typename T>
|
||||
typename std::enable_if<ViewTraits::IsLastArgResponder, void>::type
|
||||
responseImpl(T &boundViewHandler,
|
||||
const QHttpServerRequest &request,
|
||||
QTcpSocket *socket)
|
||||
{
|
||||
boundViewHandler(makeResponder(request, socket));
|
||||
}
|
||||
|
||||
bool handleRequest(const QHttpServerRequest &request, QTcpSocket *socket) final;
|
||||
|
||||
void sendResponse(const QHttpServerResponse &response,
|
||||
const QHttpServerRequest &request,
|
||||
QTcpSocket *socket);
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QHTTPSERVER_H
|
72
src/httpserver/qhttpserver_p.h
Normal file
72
src/httpserver/qhttpserver_p.h
Normal file
@ -0,0 +1,72 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 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:LGPL$
|
||||
** 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 Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or 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.GPL2 and 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-2.0.html and
|
||||
** 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/qmap.h>
|
||||
|
||||
class QHttpServerPrivate: public QAbstractHttpServerPrivate
|
||||
{
|
||||
Q_DECLARE_PUBLIC(QHttpServer)
|
||||
|
||||
public:
|
||||
QHttpServerPrivate() = default;
|
||||
|
||||
QHttpServerRouter router;
|
||||
};
|
||||
|
||||
#endif // QHTTPSERVER_P_H
|
@ -267,6 +267,11 @@ QUrl QHttpServerRequest::url() const
|
||||
return d->url;
|
||||
}
|
||||
|
||||
QUrlQuery QHttpServerRequest::query() const
|
||||
{
|
||||
return QUrlQuery(d->url.query());
|
||||
}
|
||||
|
||||
QHttpServerRequest::Method QHttpServerRequest::method() const
|
||||
{
|
||||
switch (d->httpParser.method) {
|
||||
|
@ -46,6 +46,7 @@
|
||||
#include <QtCore/qglobal.h>
|
||||
#include <QtCore/qshareddata.h>
|
||||
#include <QtCore/qurl.h>
|
||||
#include <QtCore/qurlquery.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
@ -80,6 +81,7 @@ public:
|
||||
|
||||
QString value(const QString &key) const;
|
||||
QUrl url() const;
|
||||
QUrlQuery query() const;
|
||||
Method method() const;
|
||||
QVariantMap headers() const;
|
||||
QByteArray body() const;
|
||||
|
120
src/httpserver/qhttpserverresponse.cpp
Normal file
120
src/httpserver/qhttpserverresponse.cpp
Normal file
@ -0,0 +1,120 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 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:LGPL$
|
||||
** 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 Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or 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.GPL2 and 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-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtHttpServer/qhttpserverresponse.h>
|
||||
|
||||
#include <private/qhttpserverresponse_p.h>
|
||||
|
||||
#include <QtCore/qjsondocument.h>
|
||||
#include <QtCore/qjsonobject.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
namespace {
|
||||
|
||||
const QByteArray mimeTextHtml("text/html");
|
||||
const QByteArray mimeApplicationJson("application/json");
|
||||
|
||||
}
|
||||
|
||||
QHttpServerResponse::QHttpServerResponse(QHttpServerResponse &&other)
|
||||
: d_ptr(other.d_ptr.take())
|
||||
{
|
||||
}
|
||||
|
||||
QHttpServerResponse::QHttpServerResponse(const QHttpServerResponse::StatusCode statusCode)
|
||||
: QHttpServerResponse(mimeTextHtml, QByteArray(), statusCode)
|
||||
{
|
||||
}
|
||||
|
||||
QHttpServerResponse::QHttpServerResponse(const char *data)
|
||||
: QHttpServerResponse(mimeTextHtml, QByteArray(data))
|
||||
{
|
||||
}
|
||||
|
||||
QHttpServerResponse::QHttpServerResponse(const QString &data)
|
||||
: QHttpServerResponse(mimeTextHtml, data.toUtf8())
|
||||
{
|
||||
}
|
||||
|
||||
QHttpServerResponse::QHttpServerResponse(const QByteArray &data)
|
||||
: QHttpServerResponse(mimeTextHtml, data)
|
||||
{
|
||||
}
|
||||
|
||||
QHttpServerResponse::QHttpServerResponse(const QJsonObject &data)
|
||||
: QHttpServerResponse(mimeApplicationJson, QJsonDocument(data).toJson())
|
||||
{
|
||||
}
|
||||
|
||||
QHttpServerResponse::QHttpServerResponse(const QByteArray &mimeType,
|
||||
const QByteArray &data,
|
||||
const StatusCode status)
|
||||
: QHttpServerResponse(new QHttpServerResponsePrivate{mimeType, data, status})
|
||||
{
|
||||
}
|
||||
|
||||
QHttpServerResponse::~QHttpServerResponse()
|
||||
{
|
||||
}
|
||||
|
||||
QHttpServerResponse::QHttpServerResponse(QHttpServerResponsePrivate *d)
|
||||
: d_ptr(d)
|
||||
{
|
||||
}
|
||||
|
||||
QByteArray QHttpServerResponse::data() const
|
||||
{
|
||||
Q_D(const QHttpServerResponse);
|
||||
return d->data;
|
||||
}
|
||||
|
||||
QByteArray QHttpServerResponse::mimeType() const
|
||||
{
|
||||
Q_D(const QHttpServerResponse);
|
||||
return d->mimeType;
|
||||
}
|
||||
|
||||
QHttpServerResponse::StatusCode QHttpServerResponse::statusCode() const
|
||||
{
|
||||
Q_D(const QHttpServerResponse);
|
||||
return d->statusCode;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
89
src/httpserver/qhttpserverresponse.h
Normal file
89
src/httpserver/qhttpserverresponse.h
Normal file
@ -0,0 +1,89 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 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:LGPL$
|
||||
** 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 Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or 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.GPL2 and 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-2.0.html and
|
||||
** 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);
|
||||
QHttpServerResponse& operator=(QHttpServerResponse &&other) = delete;
|
||||
|
||||
QHttpServerResponse(const StatusCode statusCode);
|
||||
QHttpServerResponse(const char *data);
|
||||
QHttpServerResponse(const QString &data);
|
||||
explicit QHttpServerResponse(const QByteArray &data);
|
||||
QHttpServerResponse(const QJsonObject &data);
|
||||
QHttpServerResponse(const QByteArray &mimeType,
|
||||
const QByteArray &data,
|
||||
const StatusCode status = StatusCode::Ok);
|
||||
virtual ~QHttpServerResponse();
|
||||
|
||||
QByteArray data() const;
|
||||
|
||||
QByteArray mimeType() const;
|
||||
|
||||
StatusCode statusCode() const;
|
||||
private:
|
||||
QHttpServerResponse(QHttpServerResponsePrivate *d);
|
||||
|
||||
QScopedPointer<QHttpServerResponsePrivate> d_ptr;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QHTTPSERVERRESPONSE_H
|
64
src/httpserver/qhttpserverresponse_p.h
Normal file
64
src/httpserver/qhttpserverresponse_p.h
Normal file
@ -0,0 +1,64 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 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:LGPL$
|
||||
** 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 Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or 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.GPL2 and 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-2.0.html and
|
||||
** 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>
|
||||
|
||||
struct QHttpServerResponsePrivate
|
||||
{
|
||||
QByteArray mimeType;
|
||||
QByteArray data;
|
||||
QHttpServerResponse::StatusCode statusCode;
|
||||
};
|
||||
|
||||
#endif // QHTTPSERVERRESPONSE_P_H
|
@ -74,6 +74,82 @@ struct QHttpServerRouterViewTraits<Ret(ClassType::*)(Args...) const>
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
// Tools used to check position of special arguments (QHttpServerResponder, QHttpServerRequest)
|
||||
// and unsupported types
|
||||
template<bool Last, typename Arg>
|
||||
static constexpr bool checkArgument() noexcept
|
||||
{
|
||||
static_assert(Last || !std::is_same<Arg, const QHttpServerRequest &>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be the last argument");
|
||||
static_assert(Last || !std::is_same<Arg, QHttpServerResponder &&>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be the last argument");
|
||||
|
||||
static_assert(!std::is_same<Arg, QHttpServerRequest &&>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerRequest &>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
static_assert(!std::is_same<Arg, const QHttpServerRequest *>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerRequest const*>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerRequest *>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerRequest can only be passed as a const reference");
|
||||
|
||||
static_assert(!std::is_same<Arg, QHttpServerResponder &>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
static_assert(!std::is_same<Arg, const QHttpServerResponder *const>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
static_assert(!std::is_same<Arg, const QHttpServerResponder *>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerResponder const*>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
static_assert(!std::is_same<Arg, QHttpServerResponder *>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"QHttpServerResponder can only be passed as a universal reference");
|
||||
|
||||
using Type = typename std::remove_cv<typename std::remove_reference<Arg>::type>::type;
|
||||
|
||||
static_assert(QMetaTypeId2<Type>::Defined
|
||||
|| std::is_same<Type, QHttpServerResponder>::value
|
||||
|| std::is_same<Type, QHttpServerRequest>::value,
|
||||
"ViewHandler arguments error: "
|
||||
"Type is not registered, please use the Q_DECLARE_METATYPE macro "
|
||||
"to make it known to Qt's meta-object system");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename Arg, typename ... ArgX>
|
||||
struct ArgumentsCheck {
|
||||
static constexpr bool compileCheck()
|
||||
{
|
||||
return checkArgument<false, Arg>() && ArgumentsCheck<ArgX...>::compileCheck();
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Arg>
|
||||
struct ArgumentsCheck<Arg> {
|
||||
static constexpr bool compileCheck()
|
||||
{
|
||||
return checkArgument<true, Arg>();
|
||||
}
|
||||
};
|
||||
|
||||
using Arguments = ArgumentsCheck<Args...>;
|
||||
|
||||
private:
|
||||
// Tools used to compute ArgumentCapturableCount
|
||||
template<typename T>
|
||||
@ -113,6 +189,14 @@ public:
|
||||
// BindableType is an emulation of "auto" for QHttpServerRouter::bindCapture.
|
||||
using BindableType = typename decltype(
|
||||
bindTypeHelper(typename QtPrivate::Indexes<ArgumentPlaceholdersCount>::Value{}))::Type;
|
||||
|
||||
static constexpr bool IsLastArgRequest = std::is_same<
|
||||
typename Arg<ArgumentCount - 1>::Type, QHttpServerRequest>::value;
|
||||
|
||||
static constexpr bool IsLastArgResponder = std::is_same<
|
||||
typename Arg<ArgumentCount - 1>::Type, QHttpServerResponder&&>::value;
|
||||
|
||||
static constexpr bool IsLastArgNonSpecial = !(IsLastArgRequest || IsLastArgResponder);
|
||||
};
|
||||
|
||||
template <typename ClassType, typename Ret>
|
||||
@ -129,6 +213,16 @@ struct QHttpServerRouterViewTraits<Ret(ClassType::*)() const>
|
||||
static constexpr const auto ArgumentPlaceholdersCount = 0;
|
||||
|
||||
using BindableType = decltype(std::function<Ret()>{});
|
||||
|
||||
static constexpr bool IsLastArgRequest = false;
|
||||
static constexpr bool IsLastArgResponder = false;
|
||||
static constexpr bool IsLastArgNonSpecial = true;
|
||||
|
||||
struct ArgumentsCheck {
|
||||
static constexpr bool compileCheck() { return true; }
|
||||
};
|
||||
|
||||
using Arguments = ArgumentsCheck;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -3,5 +3,6 @@ TEMPLATE = subdirs
|
||||
SUBDIRS = \
|
||||
cmake \
|
||||
qabstracthttpserver \
|
||||
qhttpserver \
|
||||
qhttpserverresponder \
|
||||
qhttpserverrouter
|
||||
|
5
tests/auto/qhttpserver/qhttpserver.pro
Normal file
5
tests/auto/qhttpserver/qhttpserver.pro
Normal file
@ -0,0 +1,5 @@
|
||||
CONFIG += testcase
|
||||
TARGET = tst_qhttpserver
|
||||
SOURCES += tst_qhttpserver.cpp
|
||||
|
||||
QT = httpserver httpserver-private testlib
|
348
tests/auto/qhttpserver/tst_qhttpserver.cpp
Normal file
348
tests/auto/qhttpserver/tst_qhttpserver.cpp
Normal file
@ -0,0 +1,348 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2018 The Qt Company Ltd.
|
||||
** Contact: https://www.qt.io/licensing/
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** 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 Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 3 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL3 included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 3 requirements
|
||||
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 2.0 or (at your option) the GNU General
|
||||
** Public license version 3 or 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.GPL2 and 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-2.0.html and
|
||||
** https://www.gnu.org/licenses/gpl-3.0.html.
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtHttpServer/qhttpserver.h>
|
||||
#include <QtHttpServer/qhttpserverrequest.h>
|
||||
#include <QtHttpServer/qhttpserverrouterrule.h>
|
||||
|
||||
#include <private/qhttpserverrouterrule_p.h>
|
||||
|
||||
#include <QtTest/qtest.h>
|
||||
#include <QtTest/qsignalspy.h>
|
||||
|
||||
#include <QtCore/qurl.h>
|
||||
#include <QtCore/qstring.h>
|
||||
#include <QtCore/qlist.h>
|
||||
#include <QtCore/qbytearray.h>
|
||||
|
||||
#include <QtNetwork/qnetworkaccessmanager.h>
|
||||
#include <QtNetwork/qnetworkreply.h>
|
||||
#include <QtNetwork/qnetworkrequest.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QueryRequireRouterRule : public QHttpServerRouterRule
|
||||
{
|
||||
public:
|
||||
QueryRequireRouterRule(const QString &pathPattern,
|
||||
const char *queryKey,
|
||||
RouterHandler &&routerHandler)
|
||||
: QHttpServerRouterRule(pathPattern, std::forward<RouterHandler>(routerHandler)),
|
||||
m_queryKey(queryKey)
|
||||
{
|
||||
}
|
||||
|
||||
bool matches(const QHttpServerRequest &request, QRegularExpressionMatch *match) const override
|
||||
{
|
||||
if (QHttpServerRouterRule::matches(request, match)) {
|
||||
if (request.query().hasQueryItem(m_queryKey))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
const char * m_queryKey;
|
||||
};
|
||||
|
||||
class tst_QHttpServer final : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
signals:
|
||||
void test();
|
||||
|
||||
private slots:
|
||||
void initTestCase();
|
||||
void routeGet_data();
|
||||
void routeGet();
|
||||
void routePost_data();
|
||||
void routePost();
|
||||
|
||||
private:
|
||||
QHttpServer httpserver;
|
||||
QString urlBase;
|
||||
};
|
||||
|
||||
void tst_QHttpServer::initTestCase()
|
||||
{
|
||||
httpserver.route("/test", [] (QHttpServerResponder &&responder) {
|
||||
responder.write("test msg", "text/html");
|
||||
});
|
||||
|
||||
httpserver.route("/", QHttpServerRequest::Method::Get, [] () {
|
||||
return "Hello world get";
|
||||
});
|
||||
|
||||
httpserver.route("/", QHttpServerRequest::Method::Post, [] () {
|
||||
return "Hello world post";
|
||||
});
|
||||
|
||||
httpserver.route("/page/", [] (const qint32 number) {
|
||||
return QString("page: %1").arg(number);
|
||||
});
|
||||
|
||||
httpserver.route("/page/<arg>/detail", [] (const quint32 number) {
|
||||
return QString("page: %1 detail").arg(number);
|
||||
});
|
||||
|
||||
httpserver.route("/user/", [] (const QString &name) {
|
||||
return QString("%1").arg(name);
|
||||
});
|
||||
|
||||
httpserver.route("/user/<arg>/", [] (const QString &name, const QByteArray &ba) {
|
||||
return QString("%1-%2").arg(name).arg(QString::fromLatin1(ba));
|
||||
});
|
||||
|
||||
httpserver.route("/test/", [] (const QUrl &url) {
|
||||
return QString("path: %1").arg(url.path());
|
||||
});
|
||||
|
||||
httpserver.route("/api/v", [] (const float api) {
|
||||
return QString("api %1v").arg(api);
|
||||
});
|
||||
|
||||
httpserver.route("/api/v<arg>/user/", [] (const float api, const quint64 user) {
|
||||
return QString("api %1v, user id - %2").arg(api).arg(user);
|
||||
});
|
||||
|
||||
httpserver.route("/api/v<arg>/user/<arg>/settings", [] (const float api, const quint64 user,
|
||||
const QHttpServerRequest &request) {
|
||||
const auto &role = request.query().queryItemValue(QString::fromLatin1("role"));
|
||||
const auto &fragment = request.url().fragment();
|
||||
|
||||
return QString("api %1v, user id - %2, set settings role=%3#'%4'")
|
||||
.arg(api).arg(user).arg(role, fragment);
|
||||
});
|
||||
|
||||
httpserver.route<QueryRequireRouterRule>(
|
||||
"/custom/",
|
||||
"key",
|
||||
[] (const quint64 num, const QHttpServerRequest &request) {
|
||||
return QString("Custom router rule: %1, key=%2")
|
||||
.arg(num)
|
||||
.arg(request.query().queryItemValue("key"));
|
||||
});
|
||||
|
||||
urlBase = QStringLiteral("http://localhost:%1%2").arg(httpserver.listen());
|
||||
}
|
||||
|
||||
void tst_QHttpServer::routeGet_data()
|
||||
{
|
||||
QTest::addColumn<QString>("url");
|
||||
QTest::addColumn<int>("code");
|
||||
QTest::addColumn<QString>("type");
|
||||
QTest::addColumn<QString>("body");
|
||||
|
||||
QTest::addRow("hello world")
|
||||
<< "/"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "Hello world get";
|
||||
|
||||
QTest::addRow("test msg")
|
||||
<< "/test"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "test msg";
|
||||
|
||||
QTest::addRow("not found")
|
||||
<< "/not-found"
|
||||
<< 404
|
||||
<< "text/html"
|
||||
<< "";
|
||||
|
||||
QTest::addRow("arg:int")
|
||||
<< "/page/10"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "page: 10";
|
||||
|
||||
QTest::addRow("arg:-int")
|
||||
<< "/page/-10"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "page: -10";
|
||||
|
||||
QTest::addRow("arg:uint")
|
||||
<< "/page/10/detail"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "page: 10 detail";
|
||||
|
||||
QTest::addRow("arg:-uint")
|
||||
<< "/page/-10/detail"
|
||||
<< 404
|
||||
<< "text/html"
|
||||
<< "";
|
||||
|
||||
QTest::addRow("arg:string")
|
||||
<< "/user/test"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "test";
|
||||
|
||||
QTest::addRow("arg:string")
|
||||
<< "/user/test test ,!a+."
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "test test ,!a+.";
|
||||
|
||||
QTest::addRow("arg:string,ba")
|
||||
<< "/user/james/bond"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "james-bond";
|
||||
|
||||
QTest::addRow("arg:url")
|
||||
<< "/test/api/v0/cmds?val=1"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "path: api/v0/cmds";
|
||||
|
||||
QTest::addRow("arg:float 5.1")
|
||||
<< "/api/v5.1"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "api 5.1v";
|
||||
|
||||
QTest::addRow("arg:float 5.")
|
||||
<< "/api/v5."
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "api 5v";
|
||||
|
||||
QTest::addRow("arg:float 6.0")
|
||||
<< "/api/v6.0"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "api 6v";
|
||||
|
||||
QTest::addRow("arg:float,uint")
|
||||
<< "/api/v5.1/user/10"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "api 5.1v, user id - 10";
|
||||
|
||||
QTest::addRow("arg:float,uint,query")
|
||||
<< "/api/v5.2/user/11/settings?role=admin" << 200
|
||||
<< "text/html"
|
||||
<< "api 5.2v, user id - 11, set settings role=admin#''";
|
||||
|
||||
// The fragment isn't actually sent via HTTP (it's information for the user agent)
|
||||
QTest::addRow("arg:float,uint, query+fragment")
|
||||
<< "/api/v5.2/user/11/settings?role=admin#tag"
|
||||
<< 200 << "text/html"
|
||||
<< "api 5.2v, user id - 11, set settings role=admin#''";
|
||||
|
||||
QTest::addRow("custom route rule")
|
||||
<< "/custom/15"
|
||||
<< 404
|
||||
<< "text/html"
|
||||
<< "";
|
||||
|
||||
QTest::addRow("custom route rule + query")
|
||||
<< "/custom/10?key=11&g=1"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "Custom router rule: 10, key=11";
|
||||
|
||||
QTest::addRow("custom route rule + query key req")
|
||||
<< "/custom/10?g=1&key=12"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< "Custom router rule: 10, key=12";
|
||||
}
|
||||
|
||||
void tst_QHttpServer::routeGet()
|
||||
{
|
||||
QFETCH(QString, url);
|
||||
QFETCH(int, code);
|
||||
QFETCH(QString, type);
|
||||
QFETCH(QString, body);
|
||||
|
||||
QNetworkAccessManager networkAccessManager;
|
||||
const QUrl requestUrl(urlBase.arg(url));
|
||||
auto reply = networkAccessManager.get(QNetworkRequest(requestUrl));
|
||||
|
||||
QTRY_VERIFY(reply->isFinished());
|
||||
|
||||
QCOMPARE(reply->header(QNetworkRequest::ContentTypeHeader), type);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), code);
|
||||
QCOMPARE(reply->readAll(), body);
|
||||
}
|
||||
|
||||
void tst_QHttpServer::routePost_data()
|
||||
{
|
||||
QTest::addColumn<QString>("url");
|
||||
QTest::addColumn<int>("code");
|
||||
QTest::addColumn<QString>("type");
|
||||
QTest::addColumn<QString>("data");
|
||||
QTest::addColumn<QString>("body");
|
||||
|
||||
QTest::addRow("hello world")
|
||||
<< "/"
|
||||
<< 200
|
||||
<< "text/html"
|
||||
<< ""
|
||||
<< "Hello world post";
|
||||
}
|
||||
|
||||
void tst_QHttpServer::routePost()
|
||||
{
|
||||
QFETCH(QString, url);
|
||||
QFETCH(int, code);
|
||||
QFETCH(QString, type);
|
||||
QFETCH(QString, data);
|
||||
QFETCH(QString, body);
|
||||
|
||||
QNetworkAccessManager networkAccessManager;
|
||||
const QUrl requestUrl(urlBase.arg(url));
|
||||
auto reply = networkAccessManager.post(QNetworkRequest(requestUrl), data.toUtf8());
|
||||
|
||||
QTRY_VERIFY(reply->isFinished());
|
||||
|
||||
QCOMPARE(reply->header(QNetworkRequest::ContentTypeHeader), type);
|
||||
QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), code);
|
||||
QCOMPARE(reply->readAll(), body);
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
QTEST_MAIN(tst_QHttpServer)
|
||||
|
||||
#include "tst_qhttpserver.moc"
|
Loading…
x
Reference in New Issue
Block a user