cutelyst 3.9.1
A C++ Web Framework built on top of Qt, using the simple approach of Catalyst (Perl) framework.
useragent.cpp
1/*
2 * SPDX-FileCopyrightText: (C) 2019-2022 Daniel Nicoletti <dantti12@gmail.com>
3 * SPDX-License-Identifier: BSD-3-Clause
4 */
5#include "useragent.h"
6
7#include <Cutelyst/Context>
8#include <Cutelyst/Engine>
9#include <Cutelyst/Request>
10#include <Cutelyst/Response>
11
12#include <QBuffer>
13#include <QHostAddress>
14#include <QHttpMultiPart>
15#include <QJsonDocument>
16#include <QLoggingCategory>
17#include <QNetworkAccessManager>
18
19using namespace Cutelyst;
20
21Q_LOGGING_CATEGORY(C_USERAGENT, "cutelyst.useragent", QtInfoMsg)
22
23static thread_local QNetworkAccessManager m_instance;
24
25QNetworkAccessManager *Cutelyst::UA::networkAccessManager()
26{
27 return &m_instance;
28}
29
30QNetworkReply *UA::head(const QNetworkRequest &request)
31{
32 return m_instance.head(request);
33}
34
35QNetworkReply *UA::get(const QNetworkRequest &request)
36{
37 return m_instance.get(request);
38}
39
40QNetworkReply *UA::post(const QNetworkRequest &request, QIODevice *data)
41{
42 return m_instance.post(request, data);
43}
44
45QNetworkReply *UA::post(const QNetworkRequest &request, const QByteArray &data)
46{
47 return m_instance.post(request, data);
48}
49
50QNetworkReply *UA::put(const QNetworkRequest &request, QIODevice *data)
51{
52 return m_instance.put(request, data);
53}
54
55QNetworkReply *UA::put(const QNetworkRequest &request, const QByteArray &data)
56{
57 return m_instance.put(request, data);
58}
59
60QNetworkReply *UA::deleteResource(const QNetworkRequest &request)
61{
62 return m_instance.deleteResource(request);
63}
64
66 UA::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
67{
68 return m_instance.sendCustomRequest(request, verb, data);
69}
70
71QNetworkReply *UA::sendCustomRequest(const QNetworkRequest &request,
72 const QByteArray &verb,
73 const QByteArray &data)
74{
75 return m_instance.sendCustomRequest(request, verb, data);
76}
77
78QNetworkReply *UA::post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
79{
80 return m_instance.post(request, multiPart);
81}
82
83QNetworkReply *UA::put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
84{
85 return m_instance.post(request, multiPart);
86}
87
88QNetworkReply *UA::sendCustomRequest(const QNetworkRequest &request,
89 const QByteArray &verb,
90 QHttpMultiPart *multiPart)
91{
92 return m_instance.sendCustomRequest(request, verb, multiPart);
93}
94
95QNetworkReply *UA::postJson(const QNetworkRequest &request, const QJsonDocument &doc)
96{
97 QNetworkRequest jsonRequest(request);
98 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
99 QByteArrayLiteral("application/json"));
100 return m_instance.post(jsonRequest, doc.toJson(QJsonDocument::Compact));
101}
102
103QNetworkReply *UA::putJson(const QNetworkRequest &request, const QJsonDocument &doc)
104{
105 QNetworkRequest jsonRequest(request);
106 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
107 QByteArrayLiteral("application/json"));
108 return m_instance.put(jsonRequest, doc.toJson(QJsonDocument::Compact));
109}
110
111QNetworkReply *UA::sendCustomRequestJson(const QNetworkRequest &request,
112 const QByteArray &verb,
113 const QJsonDocument &doc)
114{
115 QNetworkRequest jsonRequest(request);
116 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
117 QByteArrayLiteral("application/json"));
118 return UA::sendCustomRequest(jsonRequest, verb, doc.toJson(QJsonDocument::Compact));
119}
120
121QNetworkReply *UA::postJsonObject(const QNetworkRequest &request, const QJsonObject &obj)
122{
123 QNetworkRequest jsonRequest(request);
124 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
125 QByteArrayLiteral("application/json"));
126 return m_instance.post(jsonRequest, QJsonDocument(obj).toJson(QJsonDocument::Compact));
127}
128
129QNetworkReply *UA::putJsonObject(const QNetworkRequest &request, const QJsonObject &obj)
130{
131 QNetworkRequest jsonRequest(request);
132 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
133 QByteArrayLiteral("application/json"));
134 return m_instance.put(jsonRequest, QJsonDocument(obj).toJson(QJsonDocument::Compact));
135}
136
137QNetworkReply *UA::sendCustomRequestJsonObject(const QNetworkRequest &request,
138 const QByteArray &verb,
139 const QJsonObject &obj)
140{
141 QNetworkRequest jsonRequest(request);
142 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
143 QByteArrayLiteral("application/json"));
144 return UA::sendCustomRequest(
145 jsonRequest, verb, QJsonDocument(obj).toJson(QJsonDocument::Compact));
146}
147
148QNetworkReply *UA::postJsonArray(const QNetworkRequest &request, const QJsonArray &array)
149{
150 QNetworkRequest jsonRequest(request);
151 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
152 QByteArrayLiteral("application/json"));
153 return m_instance.post(jsonRequest, QJsonDocument(array).toJson(QJsonDocument::Compact));
154}
155
156QNetworkReply *UA::putJsonArray(const QNetworkRequest &request, const QJsonArray &array)
157{
158 QNetworkRequest jsonRequest(request);
159 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
160 QByteArrayLiteral("application/json"));
161 return m_instance.put(jsonRequest, QJsonDocument(array).toJson(QJsonDocument::Compact));
162}
163
164QNetworkReply *UA::sendCustomRequestJsonArray(const QNetworkRequest &request,
165 const QByteArray &verb,
166 const QJsonArray &array)
167{
168 QNetworkRequest jsonRequest(request);
169 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
170 QByteArrayLiteral("application/json"));
171 return UA::sendCustomRequest(
172 jsonRequest, verb, QJsonDocument(array).toJson(QJsonDocument::Compact));
173}
174
175QNetworkReply *UA::forwardRequest(Request *request, const QUrl &destination)
176{
177 QUrl dest(request->uri());
178 dest.setHost(destination.host());
179 dest.setPort(destination.port());
180 dest.setScheme(destination.scheme());
181
182 QNetworkRequest proxyReq(dest);
183
184 const Headers reqHeaders = request->headers();
185 const auto headersData = reqHeaders.data();
186 auto it = headersData.constBegin();
187 while (it != headersData.constEnd()) {
188 proxyReq.setRawHeader(Cutelyst::Engine::camelCaseHeader(it.key()).toLatin1(),
189 it.value().toLatin1());
190 ++it;
191 }
192
193 return m_instance.sendCustomRequest(proxyReq, request->method().toLatin1(), request->body());
194}
195
196QNetworkReply *UA::forwardRequestResponse(Context *c, const QUrl &destination)
197{
198 QNetworkReply *reply = forwardRequest(c->request(), destination);
200 Headers &responseHeaders = c->response()->headers();
201 const QList<QNetworkReply::RawHeaderPair> &headers = reply->rawHeaderPairs();
202 for (const QNetworkReply::RawHeaderPair &pair : headers) {
203 responseHeaders.setHeader(QString::fromLatin1(pair.first),
204 QString::fromLatin1(pair.second));
205 }
206 c->response()->setStatus(
208 c->response()->setBody(reply);
209 });
210 return reply;
211}
212
213void UA::forwardAsync(Context *c, const QUrl &destination)
214{
215 QNetworkReply *reply = forwardRequest(c->request(), destination);
217 Headers &responseHeaders = c->response()->headers();
218 const QList<QNetworkReply::RawHeaderPair> &headers = reply->rawHeaderPairs();
219 for (const QNetworkReply::RawHeaderPair &pair : headers) {
220 responseHeaders.setHeader(QString::fromLatin1(pair.first),
221 QString::fromLatin1(pair.second));
222 }
223 c->response()->setStatus(
225 c->response()->setBody(reply);
226 c->attachAsync();
227 });
228 c->detachAsync();
229}
The Cutelyst Context.
Definition context.h:39
void attachAsync()
attachAsync
Definition context.cpp:361
void detachAsync() noexcept
Definition context.cpp:355
Response * response() const noexcept
Definition context.cpp:96
static QString camelCaseHeader(const QString &headerKey)
Definition engine.h:103
QMultiHash< QString, QString > data() const
Definition headers.h:382
void setHeader(const QString &field, const QString &value)
Definition headers.cpp:396
Headers headers() const noexcept
Definition request.cpp:310
QIODevice * body() const
Definition request.cpp:181
Headers & headers() noexcept
Definition response.cpp:339
void setStatus(quint16 status) noexcept
Definition response.cpp:70
void setBody(QIODevice *body)
Definition response.cpp:100
The Cutelyst namespace holds all public Cutelyst API.
Definition Mainpage.dox:8
QByteArray toJson() const const
typedef RawHeaderPair
QVariant attribute(QNetworkRequest::Attribute code) const const
const QList< RawHeaderPair > & rawHeaderPairs() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
QString fromLatin1(const char *str, int size)
QByteArray toLatin1() const const
QString host(ComponentFormattingOptions options) const const
int port(int defaultPort) const const
QString scheme() const const
uint toUInt(bool *ok) const const