Skip to content

Commit

Permalink
Introduce QHttpServer
Browse files Browse the repository at this point in the history
QHttpServer provides a simplified interface to QAbstractHttpServer and
QHttpServerRouter.

Change-Id: I884204aa8140bbab4c0d6a8ab4c798e0b2470e29
Reviewed-by: Paul Wicking <[email protected]>
Reviewed-by: Edward Welbourne <[email protected]>
  • Loading branch information
msvetkin committed Jan 25, 2019
1 parent a856556 commit 540daf8
Show file tree
Hide file tree
Showing 17 changed files with 1,238 additions and 0 deletions.
4 changes: 4 additions & 0 deletions examples/examples.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
TEMPLATE = subdirs

SUBDIRS = \
httpserver
5 changes: 5 additions & 0 deletions examples/httpserver/httpserver.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
TEMPLATE = subdirs

SUBDIRS = \
simple

118 changes: 118 additions & 0 deletions examples/httpserver/simple/main.cpp
Original file line number Diff line number Diff line change
@@ -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:https://127.0.0.1:%1/").arg(port);
return 0;
}

qDebug() << QCoreApplication::translate(
"QHttpServerExample", "Running on http:https://127.0.0.1:%1/ (Press CTRL+C to quit)").arg(port);

return app.exec();
}
11 changes: 11 additions & 0 deletions examples/httpserver/simple/simple.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
requires(qtHaveModule(httpserver))

TEMPLATE = app

QT += httpserver

SOURCES += \
main.cpp

target.path = $$[QT_INSTALL_EXAMPLES]/httpserver/simple
INSTALLS += target
6 changes: 6 additions & 0 deletions src/httpserver/httpserver.pro
Original file line number Diff line number Diff line change
Expand Up @@ -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 \
Expand All @@ -22,8 +26,10 @@ HEADERS += \

SOURCES += \
qabstracthttpserver.cpp \
qhttpserver.cpp \
qhttpserverrequest.cpp \
qhttpserverresponder.cpp \
qhttpserverresponse.cpp \
qhttpserverrouter.cpp \
qhttpserverrouterrule.cpp

Expand Down
150 changes: 150 additions & 0 deletions src/httpserver/qhttpserver.cpp
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 540daf8

Please sign in to comment.