// Copyright (C) 2019 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #ifndef QHTTPSERVERROUTERRULE_H #define QHTTPSERVERROUTERRULE_H #include #include #include #include #include #include #include QT_BEGIN_NAMESPACE class QString; class QHttpServerRequest; class QHttpServerResponder; class QRegularExpressionMatch; class QHttpServerRouter; class QHttpServerRouterRulePrivate; class Q_HTTPSERVER_EXPORT QHttpServerRouterRule { Q_DECLARE_PRIVATE(QHttpServerRouterRule) Q_DISABLE_COPY_MOVE(QHttpServerRouterRule) private: using RouterHandlerPrototype = void (*)(const QRegularExpressionMatch &, const QHttpServerRequest &, QHttpServerResponder &); template using if_routerhandler_prototype_compatible = typename std::enable_if< QtPrivate::AreFunctionsCompatible::value, bool>::type; QHttpServerRouterRule(const QString &pathPattern, const QHttpServerRequest::Methods methods, const QObject *context, QtPrivate::QSlotObjectBase *slotObjRaw); public: #ifdef Q_QDOC template QHttpServerRouterRule( const QString &pathPattern, const QHttpServerRequest::Methods methods, const QObject *receiver, Functor &&slot); template QHttpServerRouterRule( const QString &pathPattern, const QObject *receiver, Functor &&slot); #else template = true> QHttpServerRouterRule( const QString &pathPattern, const typename QtPrivate::ContextTypeForFunctor::ContextType *context, Handler &&func) : QHttpServerRouterRule( pathPattern, QHttpServerRequest::Method::AnyKnown, context, QtPrivate::makeCallableObject(std::forward(func))) { } template = true> QHttpServerRouterRule( const QString &pathPattern, const QHttpServerRequest::Methods methods, const typename QtPrivate::ContextTypeForFunctor::ContextType *context, Handler &&func) : QHttpServerRouterRule( pathPattern, methods, context, QtPrivate::makeCallableObject(std::forward(func))) { } #endif #ifdef Q_QDOC template > static typename ViewTraits::BindableType bindCaptured( QObject *receiver, Functor &&slot, const QRegularExpressionMatch &match) const; # else template> static typename ViewTraits::BindableType bindCaptured( const typename QtPrivate::ContextTypeForFunctor::ContextType *context, ViewHandler &&handler, const QRegularExpressionMatch &match) { return bindCapturedImpl( context, std::forward(handler), match, typename ViewTraits::Arguments::CapturableIndexes{}); } #endif const QObject *contextObject() const; virtual ~QHttpServerRouterRule(); protected: bool exec(const QHttpServerRequest &request, QHttpServerResponder &responder) const; bool hasValidMethods() const; bool createPathRegexp(std::initializer_list metaTypes, const QHash &converters); virtual bool matches(const QHttpServerRequest &request, QRegularExpressionMatch *match) const; QHttpServerRouterRule(QHttpServerRouterRulePrivate *d); // Implementation of C++20 std::bind_front() in C++17 template static auto bind_front(F &&f, Args &&...args) { return [f = std::forward(f), args = std::make_tuple(std::forward(args)...)](auto &&...callArgs) { return std::apply(f, std::tuple_cat(args, std::forward_as_tuple(std::forward( callArgs)...))); }; } template static typename ViewTraits::BindableType bindCapturedImpl( const typename QtPrivate::ContextTypeForFunctor::ContextType *context, ViewHandler &&handler, const QRegularExpressionMatch &match, std::index_sequence) { if constexpr (std::is_member_function_pointer_v) { return bind_front( handler, const_cast::ContextType*>(context), QVariant(match.captured(Cx + 1)) .value::CleanType>()...); } else { Q_UNUSED(context); return bind_front( handler, QVariant(match.captured(Cx + 1)) .value::CleanType>()...); } } private: std::unique_ptr d_ptr; friend class QHttpServerRouter; }; QT_END_NAMESPACE #endif // QHTTPSERVERROUTERRULE_H