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