cutelyst 4.3.0
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
urifor.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2017-2022 Daniel Nicoletti <dantti12@gmail.com>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5#include "urifor.h"
6
7#include <Context>
8#include <Cutelyst/Context>
9#include <Cutelyst/ParamsMultiMap>
10#include <cutelee/exception.h>
11#include <cutelee/parser.h>
12
13#include <QDebug>
14
15UriFor::UriFor(const QString &path, const QStringList &args, Cutelee::Parser *parser)
16 : Cutelee::Node(parser)
17 , m_path(path, parser)
18{
19 bool foundQuery = false;
20 for (const QString &expression : args) {
21 // WE require the QUERY keyword to know when we are dealing with query values
22 if (expression.compare(u"QUERY") == 0) {
23 foundQuery = true;
24 continue;
25 }
26
27 if (foundQuery) {
28 m_queryExpressions.push_back(Cutelee::FilterExpression(expression, parser));
29 } else {
30 m_argsExpressions.push_back(Cutelee::FilterExpression(expression, parser));
31 }
32 }
33 std::reverse(m_queryExpressions.begin(), m_queryExpressions.end());
34}
35
36std::pair<QString, QString> splitQuery(const QString &query)
37{
38 std::pair<QString, QString> ret;
39
40 ret.first = query.section(QLatin1Char('='), 0, 0);
41 ret.second = query.section(QLatin1Char('='), 1);
42
43 return ret;
44}
45
46void UriFor::render(Cutelee::OutputStream *stream, Cutelee::Context *gc) const
47{
48 // In case cutelyst context is not set as "c"
49 auto c = gc->lookup(m_cutelystContext).value<Cutelyst::Context *>();
50 if (!c) {
51 const QVariantHash hash = gc->stackHash(0);
52 auto it = hash.constBegin();
53 while (it != hash.constEnd()) {
54 if (it.value().userType() == qMetaTypeId<Cutelyst::Context *>()) {
55 c = it.value().value<Cutelyst::Context *>();
56 if (c) {
57 m_cutelystContext = it.key();
58 break;
59 }
60 }
61 ++it;
62 }
63
64 if (!c) {
65 return;
66 }
67 }
68
69 QString path;
70 QStringList args;
71 Cutelyst::ParamsMultiMap queryValues;
72
73 QVariant pathVar = m_path.resolve(gc);
74 if (pathVar.userType() == qMetaTypeId<Cutelee::SafeString>()) {
75 path = pathVar.value<Cutelee::SafeString>().get();
76 } else if (pathVar.typeId() == QMetaType::QString) {
77 path = pathVar.toString();
78 } else {
79 qWarning() << "c_uri_for PATH is not a valid type";
80 return;
81 }
82
83 for (const Cutelee::FilterExpression &exp : m_argsExpressions) {
84 QVariant var = exp.resolve(gc);
85 if (var.userType() == qMetaTypeId<Cutelee::SafeString>()) {
86 args << var.value<Cutelee::SafeString>().get();
87 } else if (var.typeId() == QMetaType::QString) {
88 args << var.toString();
89 } else if (var.typeId() == QMetaType::QStringList) {
90 args << var.toStringList();
91 }
92 }
93
94 for (const Cutelee::FilterExpression &exp : m_queryExpressions) {
95 QVariant var = exp.resolve(gc);
96 if (var.userType() == qMetaTypeId<Cutelyst::ParamsMultiMap>()) {
97 auto map = var.value<Cutelyst::ParamsMultiMap>();
98 queryValues.unite(map);
99 } else if (var.userType() == qMetaTypeId<Cutelee::SafeString>()) {
100 auto query = splitQuery(var.value<Cutelee::SafeString>().get());
101 queryValues.insert(query.first, query.second);
102 } else if (var.typeId() == QMetaType::QString) {
103 auto query = splitQuery(var.toString());
104 queryValues.insert(query.first, query.second);
105 } else if (var.typeId() == QMetaType::QStringList) {
106 const auto queries = var.toStringList();
107 for (const QString &str : queries) {
108 auto query = splitQuery(str);
109 queryValues.insert(query.first, query.second);
110 }
111 }
112 }
113
114 *stream << c->uriFor(path, args, queryValues).toString(QUrl::FullyEncoded);
115}
116
117Cutelee::Node *UriForTag::getNode(const QString &tagContent, Cutelee::Parser *p) const
118{
119 // You almost always want to use smartSplit.
120 QStringList parts = smartSplit(tagContent);
121
122 parts.removeFirst(); // Not interested in the name of the tag.
123 if (parts.isEmpty()) {
124 throw Cutelee::Exception(Cutelee::TagSyntaxError,
125 QStringLiteral("c_uri_for requires at least the path"));
126 }
127
128 return new UriFor(parts.first(), parts.mid(1), p);
129}
130
131#include "moc_urifor.cpp"
The Cutelyst Context.
Definition context.h:42
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * get(const QNetworkRequest &request)
Definition useragent.cpp:35
T & first()
bool isEmpty() const const
QList< T > mid(qsizetype pos, qsizetype length) const const
void removeFirst()
QMultiMap::iterator insert(QMultiMap::const_iterator pos, const Key &key, const T &value)
QMultiMap< Key, T > & unite(QMultiMap< Key, T > &&other)
QString first(qsizetype n) const const
QString section(QChar sep, qsizetype start, qsizetype end, QString::SectionFlags flags) const const
FullyEncoded
QString toString() const const
QStringList toStringList() const const
int typeId() const const
int userType() const const
T value() const const