| 1 | // Copyright (C) 2019 The Qt Company Ltd. |
| 2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only |
| 3 | // Qt-Security score:significant reason:default |
| 4 | |
| 5 | #ifndef QHTTPSERVERROUTERRULE_H |
| 6 | #define QHTTPSERVERROUTERRULE_H |
| 7 | |
| 8 | #include <QtHttpServer/qhttpserverrequest.h> |
| 9 | #include <QtHttpServer/qhttpserverresponder.h> |
| 10 | #include <QtHttpServer/qhttpserverrouterviewtraits.h> |
| 11 | |
| 12 | #include <QtCore/qcontainerfwd.h> |
| 13 | #include <QtCore/qregularexpression.h> |
| 14 | |
| 15 | #include <initializer_list> |
| 16 | #include <memory> |
| 17 | |
| 18 | QT_BEGIN_NAMESPACE |
| 19 | |
| 20 | class QString; |
| 21 | class QHttpServerRequest; |
| 22 | class QHttpServerResponder; |
| 23 | class QRegularExpressionMatch; |
| 24 | class QHttpServerRouter; |
| 25 | |
| 26 | class QHttpServerRouterRulePrivate; |
| 27 | class Q_HTTPSERVER_EXPORT QHttpServerRouterRule |
| 28 | { |
| 29 | Q_DECLARE_PRIVATE(QHttpServerRouterRule) |
| 30 | Q_DISABLE_COPY_MOVE(QHttpServerRouterRule) |
| 31 | |
| 32 | private: |
| 33 | using RouterHandlerPrototype = void (*)(const QRegularExpressionMatch &, |
| 34 | const QHttpServerRequest &, QHttpServerResponder &); |
| 35 | |
| 36 | template <typename T> |
| 37 | using if_routerhandler_prototype_compatible = typename std::enable_if< |
| 38 | QtPrivate::AreFunctionsCompatible<RouterHandlerPrototype, T>::value, bool>::type; |
| 39 | |
| 40 | QHttpServerRouterRule(const QString &pathPattern, const QHttpServerRequest::Methods methods, |
| 41 | const QObject *context, QtPrivate::QSlotObjectBase *slotObjRaw); |
| 42 | |
| 43 | public: |
| 44 | #ifdef Q_QDOC |
| 45 | template <typename Functor> |
| 46 | QHttpServerRouterRule( |
| 47 | const QString &pathPattern, const QHttpServerRequest::Methods methods, |
| 48 | const QObject *receiver, |
| 49 | Functor &&slot); |
| 50 | |
| 51 | template <typename Functor> |
| 52 | QHttpServerRouterRule( |
| 53 | const QString &pathPattern, |
| 54 | const QObject *receiver, |
| 55 | Functor &&slot); |
| 56 | #else |
| 57 | template <typename Handler, if_routerhandler_prototype_compatible<Handler> = true> |
| 58 | QHttpServerRouterRule( |
| 59 | const QString &pathPattern, |
| 60 | const typename QtPrivate::ContextTypeForFunctor<Handler>::ContextType *context, |
| 61 | Handler &&func) |
| 62 | : QHttpServerRouterRule( |
| 63 | pathPattern, QHttpServerRequest::Method::AnyKnown, context, |
| 64 | QtPrivate::makeCallableObject<RouterHandlerPrototype>(std::forward<Handler>(func))) |
| 65 | { |
| 66 | } |
| 67 | |
| 68 | template <typename Handler, if_routerhandler_prototype_compatible<Handler> = true> |
| 69 | QHttpServerRouterRule( |
| 70 | const QString &pathPattern, const QHttpServerRequest::Methods methods, |
| 71 | const typename QtPrivate::ContextTypeForFunctor<Handler>::ContextType *context, |
| 72 | Handler &&func) |
| 73 | : QHttpServerRouterRule( |
| 74 | pathPattern, methods, context, |
| 75 | QtPrivate::makeCallableObject<RouterHandlerPrototype>(std::forward<Handler>(func))) |
| 76 | { |
| 77 | } |
| 78 | #endif |
| 79 | |
| 80 | #ifdef Q_QDOC |
| 81 | template <typename Functor, typename ViewTraits = QHttpServerRouterViewTraits<Functor>> |
| 82 | static typename ViewTraits::BindableType bindCaptured( |
| 83 | QObject *receiver, |
| 84 | Functor &&slot, |
| 85 | const QRegularExpressionMatch &match) const; |
| 86 | # else |
| 87 | template<typename ViewHandler, typename ViewTraits = QHttpServerRouterViewTraits<ViewHandler>> |
| 88 | static typename ViewTraits::BindableType bindCaptured( |
| 89 | const typename QtPrivate::ContextTypeForFunctor<ViewHandler>::ContextType *context, |
| 90 | ViewHandler &&handler, |
| 91 | const QRegularExpressionMatch &match) |
| 92 | { |
| 93 | return bindCapturedImpl<ViewHandler, ViewTraits>( |
| 94 | context, std::forward<ViewHandler>(handler), match, |
| 95 | typename ViewTraits::Arguments::CapturableIndexes{}); |
| 96 | } |
| 97 | #endif |
| 98 | |
| 99 | const QObject *contextObject() const; |
| 100 | |
| 101 | virtual ~QHttpServerRouterRule(); |
| 102 | |
| 103 | protected: |
| 104 | bool exec(const QHttpServerRequest &request, QHttpServerResponder &responder) const; |
| 105 | |
| 106 | bool hasValidMethods() const; |
| 107 | |
| 108 | bool createPathRegexp(std::initializer_list<QMetaType> metaTypes, |
| 109 | const QHash<QMetaType, QString> &converters); |
| 110 | |
| 111 | virtual bool matches(const QHttpServerRequest &request, |
| 112 | QRegularExpressionMatch *match) const; |
| 113 | |
| 114 | QHttpServerRouterRule(QHttpServerRouterRulePrivate *d); |
| 115 | |
| 116 | // Implementation of C++20 std::bind_front() in C++17 |
| 117 | template<typename F, typename... Args> |
| 118 | static auto bind_front(F &&f, Args &&...args) |
| 119 | { |
| 120 | return [f = std::forward<F>(f), |
| 121 | args = std::make_tuple(std::forward<Args>(args)...)](auto &&...callArgs) { |
| 122 | return std::apply(f, |
| 123 | std::tuple_cat(args, |
| 124 | std::forward_as_tuple(std::forward<decltype(callArgs)>( |
| 125 | callArgs)...))); |
| 126 | }; |
| 127 | } |
| 128 | |
| 129 | template<typename ViewHandler, typename ViewTraits, size_t... Cx> |
| 130 | static typename ViewTraits::BindableType bindCapturedImpl( |
| 131 | const typename QtPrivate::ContextTypeForFunctor<ViewHandler>::ContextType *context, |
| 132 | ViewHandler &&handler, |
| 133 | const QRegularExpressionMatch &match, |
| 134 | std::index_sequence<Cx...>) |
| 135 | { |
| 136 | if constexpr (std::is_member_function_pointer_v<ViewHandler>) { |
| 137 | return bind_front( |
| 138 | handler, const_cast<typename QtPrivate::ContextTypeForFunctor<ViewHandler>::ContextType*>(context), |
| 139 | QVariant(match.captured(nth: Cx + 1)) |
| 140 | .value<typename ViewTraits::Arguments::template Arg<Cx>::CleanType>()...); |
| 141 | } else { |
| 142 | Q_UNUSED(context); |
| 143 | return bind_front( |
| 144 | handler, |
| 145 | QVariant(match.captured(nth: Cx + 1)) |
| 146 | .value<typename ViewTraits::Arguments::template Arg<Cx>::CleanType>()...); |
| 147 | } |
| 148 | } |
| 149 | |
| 150 | private: |
| 151 | std::unique_ptr<QHttpServerRouterRulePrivate> d_ptr; |
| 152 | |
| 153 | friend class QHttpServerRouter; |
| 154 | }; |
| 155 | |
| 156 | QT_END_NAMESPACE |
| 157 | |
| 158 | #endif // QHTTPSERVERROUTERRULE_H |
| 159 | |