158 lines
5.8 KiB
C++
158 lines
5.8 KiB
C++
// 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, int... Cx>
|
|
static typename ViewTraits::BindableType bindCapturedImpl(
|
|
const typename QtPrivate::ContextTypeForFunctor<ViewHandler>::ContextType *context,
|
|
ViewHandler &&handler,
|
|
const QRegularExpressionMatch &match,
|
|
QtPrivate::IndexesList<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
|