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
15using namespace Qt::StringLiterals;
16
17UriFor::UriFor(const QString &path, const QStringList &args, Cutelee::Parser *parser)
18 : Cutelee::Node(parser)
19 , m_path(path, parser)
20{
21 bool foundQuery = false;
22 for (const QString &expression : args) {
23 // WE require the QUERY keyword to know when we are dealing with query values
24 if (expression.compare(u"QUERY") == 0) {
25 foundQuery = true;
26 continue;
27 }
28
29 if (foundQuery) {
30 m_queryExpressions.push_back(Cutelee::FilterExpression(expression, parser));
31 } else {
32 m_argsExpressions.push_back(Cutelee::FilterExpression(expression, parser));
33 }
34 }
35 std::reverse(m_queryExpressions.begin(), m_queryExpressions.end());
36}
37
38std::pair<QString, QString> splitQuery(const QString &query)
39{
40 std::pair<QString, QString> ret;
41
42 ret.first = query.section(u'=', 0, 0);
43 ret.second = query.section(u'=', 1);
44
45 return ret;
46}
47
48void UriFor::render(Cutelee::OutputStream *stream, Cutelee::Context *gc) const
49{
50 // In case cutelyst context is not set as "c"
51 auto c = gc->lookup(m_cutelystContext).value<Cutelyst::Context *>();
52 if (!c) {
53 const QVariantHash hash = gc->stackHash(0);
54 for (const auto &[key, value] : hash.asKeyValueRange()) {
55 if (value.userType() == qMetaTypeId<Cutelyst::Context *>()) {
56 c = value.value<Cutelyst::Context *>();
57 if (c) {
58 m_cutelystContext = key;
59 break;
60 }
61 }
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 u"c_uri_for requires at least the path"_s);
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