cutelyst 5.0.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 for (const auto &[key, value] : hash.asKeyValueRange()) {
53 if (value.userType() == qMetaTypeId<Cutelyst::Context *>()) {
54 c = value.value<Cutelyst::Context *>();
55 if (c) {
56 m_cutelystContext = key;
57 break;
58 }
59 }
60 }
61
62 if (!c) {
63 return;
64 }
65 }
66
67 QString path;
68 QStringList args;
69 Cutelyst::ParamsMultiMap queryValues;
70
71 QVariant pathVar = m_path.resolve(gc);
72 if (pathVar.userType() == qMetaTypeId<Cutelee::SafeString>()) {
73 path = pathVar.value<Cutelee::SafeString>().get();
74 } else if (pathVar.typeId() == QMetaType::QString) {
75 path = pathVar.toString();
76 } else {
77 qWarning() << "c_uri_for PATH is not a valid type";
78 return;
79 }
80
81 for (const Cutelee::FilterExpression &exp : m_argsExpressions) {
82 QVariant var = exp.resolve(gc);
83 if (var.userType() == qMetaTypeId<Cutelee::SafeString>()) {
84 args << var.value<Cutelee::SafeString>().get();
85 } else if (var.typeId() == QMetaType::QString) {
86 args << var.toString();
87 } else if (var.typeId() == QMetaType::QStringList) {
88 args << var.toStringList();
89 }
90 }
91
92 for (const Cutelee::FilterExpression &exp : m_queryExpressions) {
93 QVariant var = exp.resolve(gc);
94 if (var.userType() == qMetaTypeId<Cutelyst::ParamsMultiMap>()) {
95 auto map = var.value<Cutelyst::ParamsMultiMap>();
96 queryValues.unite(map);
97 } else if (var.userType() == qMetaTypeId<Cutelee::SafeString>()) {
98 auto query = splitQuery(var.value<Cutelee::SafeString>().get());
99 queryValues.insert(query.first, query.second);
100 } else if (var.typeId() == QMetaType::QString) {
101 auto query = splitQuery(var.toString());
102 queryValues.insert(query.first, query.second);
103 } else if (var.typeId() == QMetaType::QStringList) {
104 const auto queries = var.toStringList();
105 for (const QString &str : queries) {
106 auto query = splitQuery(str);
107 queryValues.insert(query.first, query.second);
108 }
109 }
110 }
111
112 *stream << c->uriFor(path, args, queryValues).toString(QUrl::FullyEncoded);
113}
114
115Cutelee::Node *UriForTag::getNode(const QString &tagContent, Cutelee::Parser *p) const
116{
117 // You almost always want to use smartSplit.
118 QStringList parts = smartSplit(tagContent);
119
120 parts.removeFirst(); // Not interested in the name of the tag.
121 if (parts.isEmpty()) {
122 throw Cutelee::Exception(Cutelee::TagSyntaxError,
123 QStringLiteral("c_uri_for requires at least the path"));
124 }
125
126 return new UriFor(parts.first(), parts.mid(1), p);
127}
128
129#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