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
18QT_BEGIN_NAMESPACE
19
20class QString;
21class QHttpServerRequest;
22class QHttpServerResponder;
23class QRegularExpressionMatch;
24class QHttpServerRouter;
25
26class QHttpServerRouterRulePrivate;
27class Q_HTTPSERVER_EXPORT QHttpServerRouterRule
28{
29 Q_DECLARE_PRIVATE(QHttpServerRouterRule)
30 Q_DISABLE_COPY_MOVE(QHttpServerRouterRule)
31
32private:
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
43public:
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
103protected:
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
150private:
151 std::unique_ptr<QHttpServerRouterRulePrivate> d_ptr;
152
153 friend class QHttpServerRouter;
154};
155
156QT_END_NAMESPACE
157
158#endif // QHTTPSERVERROUTERRULE_H
159

source code of qthttpserver/src/httpserver/qhttpserverrouterrule.h