summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMikhail Svetkin <mikhail.svetkin@gmail.com>2020-04-29 22:06:00 +0200
committerMikhail Svetkin <mikhail.svetkin@gmail.com>2020-05-14 20:36:31 +0200
commite0fa37441136aa1ca826b396aeb97726b2c04ade (patch)
tree69e3f4d8214b35fd97f8a3ea0b7d71fae4bc431d
parentf28694ea2c6ef25c2803df0916891dd0f33a3e4e (diff)
Add QHttpServer::afterRequest
This function allows to register a function to be run after each request. Task-number: QTBUG-77090 Change-Id: I40dd4c1e9a447fbe034149ffc1923c7c814cf0e9 Reviewed-by: Mikhail Svetkin <mikhail.svetkin@gmail.com>
-rw-r--r--examples/httpserver/CMakeLists.txt1
-rw-r--r--examples/httpserver/afterrequest/CMakeLists.txt27
-rw-r--r--examples/httpserver/afterrequest/afterrequest.pro13
-rw-r--r--examples/httpserver/afterrequest/main.cpp80
-rw-r--r--examples/httpserver/httpserver.pro1
-rw-r--r--src/httpserver/CMakeLists.txt9
-rw-r--r--src/httpserver/httpserver.pro4
-rw-r--r--src/httpserver/qhttpserver.cpp48
-rw-r--r--src/httpserver/qhttpserver.h63
-rw-r--r--src/httpserver/qhttpserver_p.h3
-rw-r--r--src/httpserver/qhttpserverresponse.cpp11
-rw-r--r--src/httpserver/qhttpserverresponse.h4
-rw-r--r--src/httpserver/qhttpserverrouterviewtraits.h255
-rw-r--r--src/httpserver/qhttpserverviewtraits.h109
-rw-r--r--src/httpserver/qhttpserverviewtraits_impl.h194
-rw-r--r--tests/auto/qhttpserver/tst_qhttpserver.cpp35
-rw-r--r--tests/auto/qhttpserverrouter/tst_qhttpserverrouter.cpp36
17 files changed, 643 insertions, 250 deletions
diff --git a/examples/httpserver/CMakeLists.txt b/examples/httpserver/CMakeLists.txt
index 693183c..5598230 100644
--- a/examples/httpserver/CMakeLists.txt
+++ b/examples/httpserver/CMakeLists.txt
@@ -1,3 +1,4 @@
# Generated from httpserver.pro.
+add_subdirectory(afterrequest)
add_subdirectory(simple)
diff --git a/examples/httpserver/afterrequest/CMakeLists.txt b/examples/httpserver/afterrequest/CMakeLists.txt
new file mode 100644
index 0000000..4f38035
--- /dev/null
+++ b/examples/httpserver/afterrequest/CMakeLists.txt
@@ -0,0 +1,27 @@
+# Generated from afterrequest.pro.
+
+cmake_minimum_required(VERSION 3.14)
+project(afterrequest LANGUAGES CXX)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set(CMAKE_AUTOMOC ON)
+set(CMAKE_AUTORCC ON)
+set(CMAKE_AUTOUIC ON)
+
+set(INSTALL_EXAMPLEDIR "examples/httpserver/afterrequest")
+
+find_package(Qt6 COMPONENTS HttpServer)
+
+add_executable(afterrequest
+ main.cpp
+)
+target_link_libraries(afterrequest PUBLIC
+ Qt::HttpServer
+)
+
+install(TARGETS afterrequest
+ RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
+ LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+)
diff --git a/examples/httpserver/afterrequest/afterrequest.pro b/examples/httpserver/afterrequest/afterrequest.pro
new file mode 100644
index 0000000..0602f10
--- /dev/null
+++ b/examples/httpserver/afterrequest/afterrequest.pro
@@ -0,0 +1,13 @@
+requires(qtHaveModule(httpserver))
+
+TEMPLATE = app
+
+QT = httpserver
+
+SOURCES += \
+ main.cpp
+
+target.path = $$[QT_INSTALL_EXAMPLES]/httpserver/afterrequest
+INSTALLS += target
+
+CONFIG += cmdline
diff --git a/examples/httpserver/afterrequest/main.cpp b/examples/httpserver/afterrequest/main.cpp
new file mode 100644
index 0000000..c31f0a1
--- /dev/null
+++ b/examples/httpserver/afterrequest/main.cpp
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
+** 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>
+
+int main(int argc, char *argv[])
+{
+ QCoreApplication app(argc, argv);
+
+ QHttpServer httpServer;
+ httpServer.route("/", []() {
+ return "Hello world";
+ });
+
+ httpServer.afterRequest([](QHttpServerResponse &&resp) {
+ resp.setHeader("Server", "Super server!");
+ return std::move(resp);
+ });
+
+ const auto port = httpServer.listen(QHostAddress::Any);
+ if (!port) {
+ qDebug() << QCoreApplication::translate(
+ "QHttpServerExample", "Server failed to listen on a 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();
+}
diff --git a/examples/httpserver/httpserver.pro b/examples/httpserver/httpserver.pro
index b9fe1d4..7bd69d0 100644
--- a/examples/httpserver/httpserver.pro
+++ b/examples/httpserver/httpserver.pro
@@ -1,5 +1,6 @@
TEMPLATE = subdirs
SUBDIRS = \
+ afterrequest \
simple
diff --git a/src/httpserver/CMakeLists.txt b/src/httpserver/CMakeLists.txt
index b3586eb..efcce0d 100644
--- a/src/httpserver/CMakeLists.txt
+++ b/src/httpserver/CMakeLists.txt
@@ -16,6 +16,8 @@ qt_add_module(HttpServer
qhttpserverrouter.cpp qhttpserverrouter.h qhttpserverrouter_p.h
qhttpserverrouterrule.cpp qhttpserverrouterrule.h qhttpserverrouterrule_p.h
qhttpserverrouterviewtraits.h
+ qhttpserverviewtraits.h
+ qhttpserverviewtraits_impl.h
qthttpserverglobal.h
INCLUDE_DIRECTORIES
.
@@ -45,10 +47,3 @@ qt_extend_target(HttpServer CONDITION QT_FEATURE_ssl
PUBLIC_LIBRARIES
Qt::SslServer
)
-
-qt_extend_target(HttpServer CONDITION TARGET Qt::Concurrent
- SOURCES
- qhttpserverfutureresponse.cpp qhttpserverfutureresponse.h
- PUBLIC_LIBRARIES
- Qt::Concurrent
-)
diff --git a/src/httpserver/httpserver.pro b/src/httpserver/httpserver.pro
index 20f567f..fd1a231 100644
--- a/src/httpserver/httpserver.pro
+++ b/src/httpserver/httpserver.pro
@@ -23,7 +23,9 @@ HEADERS += \
qhttpserverrouter_p.h \
qhttpserverrouterrule.h \
qhttpserverrouterrule_p.h \
- qhttpserverrouterviewtraits.h
+ qhttpserverrouterviewtraits.h \
+ qhttpserverviewtraits.h \
+ qhttpserverviewtraits_impl.h
SOURCES += \
qabstracthttpserver.cpp \
diff --git a/src/httpserver/qhttpserver.cpp b/src/httpserver/qhttpserver.cpp
index 413e3c3..fb0b67b 100644
--- a/src/httpserver/qhttpserver.cpp
+++ b/src/httpserver/qhttpserver.cpp
@@ -66,8 +66,7 @@ QHttpServer::QHttpServer(QObject *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);
+ sendResponse(QHttpServerResponder::StatusCode::NotFound, request, socket);
});
}
@@ -103,6 +102,40 @@ QHttpServer::QHttpServer(QObject *parent)
\sa QHttpServerRouter::addRule
*/
+/*! \fn template<typename ViewHandler> void afterRequest(ViewHandler &&viewHandler)
+ Register a function to be run after each request.
+
+ \c ViewHandler can only be a lambda. The lambda definition can take two
+ arguments: \c {QHttpServerResponse &&} and \c {const QHttpServerRequest&} (optional).
+
+ Examples:
+
+ \code
+
+ QHttpServer server;
+
+ // Valid:
+ server.afterRequest([] (QHttpServerResponse &&resp, const QHttpServerRequest &request) {
+ return std::move(resp);
+ }
+ server.afterRequest([] (const QHttpServerRequest &request, QHttpServerResponse &&resp) {
+ return std::move(resp);
+ }
+ server.afterRequest([] (QHttpServerResponse &&resp) { return std::move(resp); }
+
+ // Invalid (compile time error):
+ // resp must be passed by universal reference
+ server.afterRequest([] (QHttpServerResponse &resp, const QHttpServerRequest &request) {
+ return std::move(resp);
+ }
+ // request must be passed by const reference
+ server.afterRequest([] (QHttpServerResponse &&resp, QHttpServerRequest &request) {
+ return std::move(resp);
+ }
+
+ \endcode
+*/
+
/*!
Destroys a QHttpServer.
*/
@@ -119,13 +152,22 @@ QHttpServerRouter *QHttpServer::router()
return &d->router;
}
+void QHttpServer::afterRequestImpl(AfterRequestHandler &&afterRequestHandler)
+{
+ Q_D(QHttpServer);
+ d->afterRequestHandlers.push_back(std::move(afterRequestHandler));
+}
+
/*!
\internal
*/
-void QHttpServer::sendResponse(const QHttpServerResponse &response,
+void QHttpServer::sendResponse(QHttpServerResponse &&response,
const QHttpServerRequest &request,
QTcpSocket *socket)
{
+ Q_D(QHttpServer);
+ for (auto afterRequestHandler : d->afterRequestHandlers)
+ response = std::move(afterRequestHandler(std::move(response), request));
response.write(makeResponder(request, socket));
}
diff --git a/src/httpserver/qhttpserver.h b/src/httpserver/qhttpserver.h
index 6d754b1..97c5bc5 100644
--- a/src/httpserver/qhttpserver.h
+++ b/src/httpserver/qhttpserver.h
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
@@ -35,6 +36,7 @@
#include <QtHttpServer/qhttpserverrouterrule.h>
#include <QtHttpServer/qhttpserverresponse.h>
#include <QtHttpServer/qhttpserverrouterviewtraits.h>
+#include <QtHttpServer/qhttpserverviewtraits.h>
#include <tuple>
@@ -75,6 +77,57 @@ public:
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)
@@ -107,8 +160,8 @@ private:
const QHttpServerRequest &request,
QTcpSocket *socket)
{
- const QHttpServerResponse response(boundViewHandler());
- sendResponse(response, request, socket);
+ QHttpServerResponse response(boundViewHandler());
+ sendResponse(std::move(response), request, socket);
}
template<typename ViewTraits, typename T>
@@ -124,8 +177,8 @@ private:
ViewTraits::Arguments::PlaceholdersCount == 1, void>::type
responseImpl(T &boundViewHandler, const QHttpServerRequest &request, QTcpSocket *socket)
{
- const QHttpServerResponse response(boundViewHandler(request));
- sendResponse(response, request, socket);
+ QHttpServerResponse response(boundViewHandler(request));
+ sendResponse(std::move(response), request, socket);
}
template<typename ViewTraits, typename T>
@@ -150,7 +203,7 @@ private:
bool handleRequest(const QHttpServerRequest &request, QTcpSocket *socket) override final;
- void sendResponse(const QHttpServerResponse &response,
+ void sendResponse(QHttpServerResponse &&response,
const QHttpServerRequest &request,
QTcpSocket *socket);
};
diff --git a/src/httpserver/qhttpserver_p.h b/src/httpserver/qhttpserver_p.h
index 649c41f..eb39a9e 100644
--- a/src/httpserver/qhttpserver_p.h
+++ b/src/httpserver/qhttpserver_p.h
@@ -49,6 +49,8 @@
#include <QtCore/qglobal.h>
+#include <list>
+
QT_BEGIN_NAMESPACE
class QHttpServerPrivate: public QAbstractHttpServerPrivate
@@ -59,6 +61,7 @@ public:
QHttpServerPrivate() = default;
QHttpServerRouter router;
+ std::list<QHttpServer::AfterRequestHandler> afterRequestHandlers;
};
QT_END_NAMESPACE
diff --git a/src/httpserver/qhttpserverresponse.cpp b/src/httpserver/qhttpserverresponse.cpp
index 9cedeb9..5ed230e 100644
--- a/src/httpserver/qhttpserverresponse.cpp
+++ b/src/httpserver/qhttpserverresponse.cpp
@@ -40,11 +40,20 @@
QT_BEGIN_NAMESPACE
-QHttpServerResponse::QHttpServerResponse(QHttpServerResponse &&other)
+QHttpServerResponse::QHttpServerResponse(QHttpServerResponse &&other) noexcept
: d_ptr(other.d_ptr.take())
{
}
+QHttpServerResponse& QHttpServerResponse::operator=(QHttpServerResponse &&other) noexcept
+{
+ if (this == &other)
+ return *this;
+
+ qSwap(d_ptr, other.d_ptr);
+ return *this;
+}
+
QHttpServerResponse::QHttpServerResponse(
const QHttpServerResponse::StatusCode statusCode)
: QHttpServerResponse(QHttpServerLiterals::contentTypeXEmpty(),
diff --git a/src/httpserver/qhttpserverresponse.h b/src/httpserver/qhttpserverresponse.h
index 3fef112..df748cb 100644
--- a/src/httpserver/qhttpserverresponse.h
+++ b/src/httpserver/qhttpserverresponse.h
@@ -50,8 +50,8 @@ public:
QHttpServerResponse(const QHttpServerResponse &other) = delete;
QHttpServerResponse& operator=(const QHttpServerResponse &other) = delete;
- QHttpServerResponse(QHttpServerResponse &&other);
- QHttpServerResponse& operator=(QHttpServerResponse &&other) = delete;
+ QHttpServerResponse(QHttpServerResponse &&other) noexcept;
+ QHttpServerResponse& operator=(QHttpServerResponse &&other) noexcept;
QHttpServerResponse(const StatusCode statusCode);
diff --git a/src/httpserver/qhttpserverrouterviewtraits.h b/src/httpserver/qhttpserverrouterviewtraits.h
index 94fd5cc..2e812a5 100644
--- a/src/httpserver/qhttpserverrouterviewtraits.h
+++ b/src/httpserver/qhttpserverrouterviewtraits.h
@@ -1,5 +1,6 @@
/****************************************************************************
**
+** Copyright (C) 2020 Mikhail Svetkin <mikhail.svetkin@gmail.com>
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
@@ -30,14 +31,7 @@
#ifndef QHTTPSERVERROUTERVIEWTRAITS_H
#define QHTTPSERVERROUTERVIEWTRAITS_H
-#include <QtCore/qglobal.h>
-#include <QtCore/qmetatype.h>
-#include <QtCore/qnamespace.h>
-#include <QtCore/qobjectdefs.h>
-
-#include <functional>
-#include <tuple>
-#include <type_traits>
+#include <QtHttpServer/qhttpserverviewtraits_impl.h>
QT_BEGIN_NAMESPACE
@@ -46,220 +40,53 @@ class QHttpServerResponder;
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;
-};
-
template<typename ViewHandler, bool DisableStaticAssert>
-struct ViewTraitsHelper {
- using FunctionTraits = typename QtPrivate::FunctionTraits<ViewHandler>;
- using ArgumentIndexes = typename QtPrivate::Indexes<FunctionTraits::ArgumentCount>::Value;
-
- struct StaticMath {
- template <template<typename> class Predicate, bool defaultValue>
- struct Loop {
- static constexpr bool eval() noexcept {
- return defaultValue;
- }
+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;
- template<typename T, typename ... N>
- static constexpr T eval(const T it, N ...n) noexcept {
- return Predicate<T>::eval(it, eval(n...));
- }
- };
+ static constexpr bool StaticAssert =
+ DisableStaticAssert || !Value || Valid;
- 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;
- }
+ 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 Sum = Loop<SumPredicate, false>;
- using And = Loop<AndPredicate, true>;
- using Or = Sum;
- };
-
- struct Arguments {
- template<int I>
- struct StaticCheck {
- using Arg = typename FunctionTraits::template Arg<I>;
- using CleanType = typename Arg::CleanType;
+ using CheckOk = CheckAny<IsSimple, IsSpecial>;
- template<typename T, bool Clean = false>
- static constexpr bool isType() noexcept
- {
- using SelectedType =
- typename std::conditional<
- Clean,
- CleanType,
- typename Arg::Type
- >::type;
- return std::is_same<SelectedType, T>::value;
- }
+ static constexpr bool Valid = CheckOk::Valid;
+ static constexpr bool StaticAssert = CheckOk::StaticAssert;
+ };
- template<typename T>
- struct SpecialHelper {
- using CleanTypeT = typename QtPrivate::RemoveCVRef<T>::Type;
-
- static constexpr bool TypeMatched = isType<CleanTypeT, true>();
- static constexpr bool TypeCVRefMatched = isType<T>();
-
- static constexpr bool ValidPosition =
- (I == FunctionTraits::ArgumentIndexMax ||
- I == FunctionTraits::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() noexcept
- {
- static_assert(assertConditionOrder,
- "ViewHandler arguments error: "
- "QHttpServerRequest or QHttpServerResponder"
- " can only be the last argument");
- return true;
- }
- };
-
- 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() noexcept
- {
- return StaticMath::Or::eval(T::staticAssert()...);
- }
- };
-
- struct IsRequest {
- using Helper = SpecialHelper<const QHttpServerRequest &>;
- static constexpr bool Value = Helper::TypeMatched;
- static constexpr bool Valid = Helper::ValidAll;
-
- static constexpr bool staticAssert() noexcept
- {
- static_assert(Helper::assertCondition,
- "ViewHandler arguments error: "
- "QHttpServerRequest can only be passed as a const reference");
- return Helper::staticAssert();
- }
- };
-
- struct IsResponder {
- using Helper = SpecialHelper<QHttpServerResponder &&>;
- static constexpr bool Value = Helper::TypeMatched;
- static constexpr bool Valid = Helper::ValidAll;
-
- static constexpr bool staticAssert() noexcept
- {
- static_assert(Helper::assertCondition,
- "ViewHandler arguments error: "
- "QHttpServerResponder can only be passed as a universal reference");
- return Helper::staticAssert();
- }
- };
-
- using IsSpecial = CheckAny<IsRequest, IsResponder>;
-
- struct IsSimple {
- static constexpr bool Value = !IsSpecial::Value &&
- I < FunctionTraits::ArgumentCount &&
- FunctionTraits::ArgumentIndexMax != -1;
- static constexpr bool Valid = Arg::Defined;
-
- static constexpr bool assertCondition =
- DisableStaticAssert || !Value || Valid;
-
- static constexpr bool staticAssert() noexcept
- {
- static_assert(assertCondition,
- "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;
- }
- };
-
- 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 = StaticCheck<Idx>;
+ using Arg = ArgumentChecker<Idx>;
template<int Idx>
static constexpr int metaTypeId() noexcept
@@ -279,9 +106,9 @@ struct ViewTraitsHelper {
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(StaticCheck<I>::Valid...);
+ static constexpr bool Valid = StaticMath::And::eval(Arg<I>::Valid...);
static constexpr bool StaticAssert =
- StaticMath::And::eval(StaticCheck<I>::StaticAssert...);
+ StaticMath::And::eval(Arg<I>::StaticAssert...);
using Indexes = typename QtPrivate::IndexesList<I...>;
@@ -317,18 +144,20 @@ struct ViewTraitsHelper {
};
};
+
} // namespace QtPrivate
template <typename ViewHandler, bool DisableStaticAssert = false>
struct QHttpServerRouterViewTraits
{
- using Helpers = typename QtPrivate::ViewTraitsHelper<ViewHandler, DisableStaticAssert>;
+ using Helpers = typename QtPrivate::RouterViewTraitsHelper<ViewHandler, DisableStaticAssert>;
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
diff --git a/src/httpserver/qhttpserverviewtraits.h b/src/httpserver/qhttpserverviewtraits.h
new file mode 100644
index 0000000..0469ffb
--- /dev/null
+++ b/src/httpserver/qhttpserverviewtraits.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
diff --git a/src/httpserver/qhttpserverviewtraits_impl.h b/src/httpserver/qhttpserverviewtraits_impl.h
new file mode 100644
index 0000000..45c46d7
--- /dev/null
+++ b/src/httpserver/qhttpserverviewtraits_impl.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
diff --git a/tests/auto/qhttpserver/tst_qhttpserver.cpp b/tests/auto/qhttpserver/tst_qhttpserver.cpp
index 4c50463..a5feaf9 100644
--- a/tests/auto/qhttpserver/tst_qhttpserver.cpp
+++ b/tests/auto/qhttpserver/tst_qhttpserver.cpp
@@ -129,6 +129,7 @@ private slots:
void routeExtraHeaders();
void invalidRouterArguments();
void checkRouteLambdaCapture();
+ void afterRequest();
private:
void checkReply(QNetworkReply *reply, const QString &response);
@@ -289,6 +290,10 @@ void tst_QHttpServer::initTestCase()
return resp;
});
+ httpserver.afterRequest([] (QHttpServerResponse &&resp) {
+ return std::move(resp);
+ });
+
quint16 port = httpserver.listen();
if (!port)
qCritical() << "Http server listen failed";
@@ -870,6 +875,36 @@ void tst_QHttpServer::checkRouteLambdaCapture()
return;
}
+void tst_QHttpServer::afterRequest()
+{
+ httpserver.afterRequest([] (QHttpServerResponse &&resp,
+ const QHttpServerRequest &request) {
+ if (request.url().path() == "/test-after-request")
+ resp.setHeader("Arguments-Order-1", "resp, request");
+
+ return std::move(resp);
+ });
+
+ httpserver.afterRequest([] (const QHttpServerRequest &request,
+ QHttpServerResponse &&resp) {
+ if (request.url().path() == "/test-after-request")
+ resp.setHeader("Arguments-Order-2", "request, resp");
+
+ return std::move(resp);
+ });
+
+ const QUrl requestUrl(urlBase.arg("/test-after-request"));
+ auto reply = networkAccessManager.get(QNetworkRequest(requestUrl));
+
+ QTRY_VERIFY(reply->isFinished());
+
+ QCOMPARE(reply->header(QNetworkRequest::ContentTypeHeader), "application/x-empty");
+ QCOMPARE(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(), 404);
+ QCOMPARE(reply->rawHeader("Arguments-Order-1"), "resp, request");
+ QCOMPARE(reply->rawHeader("Arguments-Order-2"), "request, resp");
+ reply->deleteLater();
+}
+
void tst_QHttpServer::checkReply(QNetworkReply *reply, const QString &response) {
QTRY_VERIFY(reply->isFinished());
diff --git a/tests/auto/qhttpserverrouter/tst_qhttpserverrouter.cpp b/tests/auto/qhttpserverrouter/tst_qhttpserverrouter.cpp
index fb0c409..d68221c 100644
--- a/tests/auto/qhttpserverrouter/tst_qhttpserverrouter.cpp
+++ b/tests/auto/qhttpserverrouter/tst_qhttpserverrouter.cpp
@@ -252,8 +252,8 @@ void tst_QHttpServerRouter::viewHandlerNoArg()
"viewOneArg: Args::Last::Valid");
static_assert(Args::Last::StaticAssert,
"viewOneArg: Args::Last::StaticAssert");
- static_assert(Args::Last::isType<std::false_type>(),
- "viewNonArg: Args::Last::isType<std::false_type>()");
+ static_assert(std::is_same<Args::Last::Type, std::false_type>::value,
+ "viewNonArg: std::is_same<Args::Last::Type, std::false_type>");
using Arg1 = typename Args::template Arg<1>;
static_assert(Arg1::IsRequest::Value == 0,
@@ -272,8 +272,8 @@ void tst_QHttpServerRouter::viewHandlerNoArg()
"viewOneArg: Args::Arg<1>::Valid");
static_assert(Arg1::StaticAssert,
"viewOneArg: Args::Arg<1>::Valid::StaticAssert");
- static_assert(Arg1::isType<std::false_type>(),
- "viewNonArg: Args::Arg<1>::isType<std::false_type>()");
+ static_assert(std::is_same<Arg1::Type, std::false_type>::value,
+ "viewNonArg: std::is_same<Args::Arg<1>::Type, std::false_type>");
static_assert(Args::Valid, "viewNonArg: Args::Valid");
static_assert(Args::StaticAssert, "viewNonArg: Args::StaticAssert");
@@ -313,8 +313,8 @@ void tst_QHttpServerRouter::viewHandlerOneArg()
"viewOneArg: Args::Last::Valid");
static_assert(Args::Last::StaticAssert,
"viewOneArg: Args::Last::StaticAssert");
- static_assert(Args::Last::isType<const quint64 &>(),
- "viewNonArg: Args::Last::isType<const quint64 &>()");
+ static_assert(std::is_same<Args::Last::Type, const quint64 &>::value,
+ "viewNonArg: std::is_same<Args::Last::Type, const quint64 &>");
static_assert(Args::Valid, "viewOneArg: Args::Valid");
static_assert(Args::StaticAssert, "viewOneArg: Args::StaticAssert");
}
@@ -355,8 +355,8 @@ void tst_QHttpServerRouter::viewHandlerTwoArgs()
"viewTwoArgs: Args::Arg0::Valid");
static_assert(Arg0::StaticAssert,
"viewTwoArgs: Args::Arg0::StaticAssert");
- static_assert(Arg0::isType<const quint64 &>(),
- "viewNonArg: Args::Arg0::isType<const quint64>()");
+ static_assert(std::is_same<Arg0::Type, const quint64 &>::value,
+ "viewNonArg: std::is_same<Args::Arg0::Type, const quint64>");
using Arg1 = typename Args::template Arg<1>;
static_assert(Arg1::IsRequest::Value == 0,
@@ -380,8 +380,8 @@ void tst_QHttpServerRouter::viewHandlerTwoArgs()
// StaticAssert is disabled in tests
static_assert(Arg1::StaticAssert,
"viewOneArg: Args::Arg1::StaticAssert");
- static_assert(Arg1::isType<const QHttpServerResponder &>(),
- "viewTwoArgs: Args::Arg1::isType<const QHttpServerResponder &>>()");
+ static_assert(std::is_same<Arg1::Type, const QHttpServerResponder &>::value,
+ "viewTwoArgs: std::is_same<Args::Arg1::Type, const QHttpServerResponder &>)");
static_assert(Args::Valid == 0, "viewTwoArgs: Args::Valid == 0");
// StaticAssert is disabled in tests
@@ -422,8 +422,8 @@ void tst_QHttpServerRouter::viewHandlerResponder()
"viewResponder: Args::Last::Valid");
static_assert(Args::Last::StaticAssert,
"viewResponder: Args::Last::StaticAssert");
- static_assert(Args::Last::isType<QHttpServerResponder &&>(),
- "viewNonArg: Args::Last::isType<QHttpServerResponder &&>()");
+ static_assert(std::is_same<Args::Last::Type, QHttpServerResponder &&>::value,
+ "viewNonArg: std::is_same<Args::Last::Type, QHttpServerResponder &&>");
static_assert(Args::Valid, "viewResponder: Args::Valid");
static_assert(Args::StaticAssert, "viewResponder: Args::StaticAssert");
}
@@ -462,8 +462,8 @@ void tst_QHttpServerRouter::viewHandlerRequest()
"viewResponder: Args::Last::Valid");
static_assert(Args::Last::StaticAssert,
"viewResponder: Args::Last::StaticAssert");
- static_assert(Args::Last::isType<const QHttpServerRequest &>(),
- "viewNonArg: Args::Last::isType<const QHttpServerRequest &>()");
+ static_assert(std::is_same<Args::Last::Type, const QHttpServerRequest &>::value,
+ "viewNonArg: std::is_same<Args::Last::Type, const QHttpServerRequest &>");
static_assert(Args::Valid, "viewResponder: Args::Valid");
static_assert(Args::StaticAssert, "viewResponder: Args::StaticAssert");
}
@@ -505,8 +505,8 @@ void tst_QHttpServerRouter::viewHandlerLastTwoSpecials()
// StaticAssert is disabled in tests
static_assert(Arg0::StaticAssert,
"viewTwoSpecialArgs: Args::Arg0::StaticAssert");
- static_assert(Arg0::isType<const QHttpServerRequest &>(),
- "viewNonArg: Args::Arg0::isType<const QHttpServerRequest &>()");
+ static_assert(std::is_same<Arg0::Type, const QHttpServerRequest &>::value,
+ "viewNonArg: std::is_same<Args::Arg0::Type, const QHttpServerRequest &>");
using Arg1 = typename Args::template Arg<1>;
static_assert(Arg1::IsRequest::Value == 0,
@@ -529,8 +529,8 @@ void tst_QHttpServerRouter::viewHandlerLastTwoSpecials()
"viewTwoSpecialArgs: Args::Arg1::Valid");
static_assert(Arg1::StaticAssert,
"viewTwoSpecialArgs: Args::Arg1::StaticAssert");
- static_assert(Arg1::isType<QHttpServerResponder &&>(),
- "viewTwoSpecialArgs: Args::Arg1::isType<QHttpServerResponder &&>()");
+ static_assert(std::is_same<Arg1::Type, QHttpServerResponder &&>::value,
+ "viewTwoSpecialArgs: std::is_same<Args::Arg1::Type, QHttpServerResponder &&>");
static_assert(Args::Valid, "viewTwoSpecialArgs: Args::Valid");
// StaticAssert is disabled in tests