cutelyst 4.9.0
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", QtWarningMsg)
22
23QNetworkAccessManager *Cutelyst::UA::networkAccessManager()
24{
25 static thread_local QNetworkAccessManager m_instance;
26 m_instance.setAutoDeleteReplies(true);
27 return &m_instance;
28}
29
30QNetworkReply *UA::head(const QNetworkRequest &request)
31{
32 return networkAccessManager()->head(request);
33}
34
35QNetworkReply *UA::get(const QNetworkRequest &request)
36{
37 return networkAccessManager()->get(request);
38}
39
40QNetworkReply *UA::post(const QNetworkRequest &request, QIODevice *data)
41{
42 return networkAccessManager()->post(request, data);
43}
44
45QNetworkReply *UA::post(const QNetworkRequest &request, const QByteArray &data)
46{
47 return networkAccessManager()->post(request, data);
48}
49
50QNetworkReply *UA::put(const QNetworkRequest &request, QIODevice *data)
51{
52 return networkAccessManager()->put(request, data);
53}
54
55QNetworkReply *UA::put(const QNetworkRequest &request, const QByteArray &data)
56{
57 return networkAccessManager()->put(request, data);
58}
59
60QNetworkReply *UA::deleteResource(const QNetworkRequest &request)
61{
62 return networkAccessManager()->deleteResource(request);
63}
64
65QNetworkReply *
66 UA::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
67{
68 return networkAccessManager()->sendCustomRequest(request, verb, data);
69}
70
71QNetworkReply *UA::sendCustomRequest(const QNetworkRequest &request,
72 const QByteArray &verb,
73 const QByteArray &data)
74{
75 return networkAccessManager()->sendCustomRequest(request, verb, data);
76}
77
78QNetworkReply *UA::post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
79{
80 return networkAccessManager()->post(request, multiPart);
81}
82
83QNetworkReply *UA::put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
84{
85 return networkAccessManager()->post(request, multiPart);
86}
87
88QNetworkReply *UA::sendCustomRequest(const QNetworkRequest &request,
89 const QByteArray &verb,
90 QHttpMultiPart *multiPart)
91{
92 return networkAccessManager()->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 networkAccessManager()->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 networkAccessManager()->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 &object)
122{
123 QNetworkRequest jsonRequest(request);
124 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
125 QByteArrayLiteral("application/json"));
126 return networkAccessManager()->post(jsonRequest,
127 QJsonDocument(object).toJson(QJsonDocument::Compact));
128}
129
130QNetworkReply *UA::putJsonObject(const QNetworkRequest &request, const QJsonObject &object)
131{
132 QNetworkRequest jsonRequest(request);
133 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
134 QByteArrayLiteral("application/json"));
135 return networkAccessManager()->put(jsonRequest,
136 QJsonDocument(object).toJson(QJsonDocument::Compact));
137}
138
139QNetworkReply *UA::sendCustomRequestJsonObject(const QNetworkRequest &request,
140 const QByteArray &verb,
141 const QJsonObject &object)
142{
143 QNetworkRequest jsonRequest(request);
144 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
145 QByteArrayLiteral("application/json"));
147 jsonRequest, verb, QJsonDocument(object).toJson(QJsonDocument::Compact));
148}
149
150QNetworkReply *UA::postJsonArray(const QNetworkRequest &request, const QJsonArray &array)
151{
152 QNetworkRequest jsonRequest(request);
153 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
154 QByteArrayLiteral("application/json"));
155 return networkAccessManager()->post(jsonRequest,
156 QJsonDocument(array).toJson(QJsonDocument::Compact));
157}
158
159QNetworkReply *UA::putJsonArray(const QNetworkRequest &request, const QJsonArray &array)
160{
161 QNetworkRequest jsonRequest(request);
162 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
163 QByteArrayLiteral("application/json"));
164 return networkAccessManager()->put(jsonRequest,
165 QJsonDocument(array).toJson(QJsonDocument::Compact));
166}
167
168QNetworkReply *UA::sendCustomRequestJsonArray(const QNetworkRequest &request,
169 const QByteArray &verb,
170 const QJsonArray &array)
171{
172 QNetworkRequest jsonRequest(request);
173 jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader,
174 QByteArrayLiteral("application/json"));
176 jsonRequest, verb, QJsonDocument(array).toJson(QJsonDocument::Compact));
177}
178
179QNetworkReply *UA::forwardRequest(Request *request, const QUrl &destination)
180{
181 QUrl dest(request->uri());
182 dest.setHost(destination.host());
183 dest.setPort(destination.port());
184 dest.setScheme(destination.scheme());
185
186 QNetworkRequest proxyReq(dest);
187
188 const Headers reqHeaders = request->headers();
189 const auto headersData = reqHeaders.data();
190 auto it = headersData.begin();
191 while (it != headersData.end()) {
192 proxyReq.setRawHeader(it->key, it->value);
193 ++it;
194 }
195
196 return networkAccessManager()->sendCustomRequest(proxyReq, request->method(), request->body());
197}
198
199QNetworkReply *UA::forwardRequestResponse(Context *c, const QUrl &destination)
200{
201 QNetworkReply *reply = forwardRequest(c->request(), destination);
202 QObject::connect(reply, &QNetworkReply::finished, c, [=] {
203 Headers &responseHeaders = c->response()->headers();
204 const QList<QNetworkReply::RawHeaderPair> &headers = reply->rawHeaderPairs();
205 for (const QNetworkReply::RawHeaderPair &pair : headers) {
206 responseHeaders.pushHeader(pair.first, pair.second);
207 }
208 c->response()->setStatus(
209 quint16(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toUInt()));
210 c->response()->setBody(reply->readAll());
211 });
212 return reply;
213}
214
215void UA::forwardAsync(Context *c, const QUrl &destination)
216{
217 ASync a;
218 QNetworkReply *reply = forwardRequest(c->request(), destination);
219 QObject::connect(reply, &QNetworkReply::finished, c, [reply, a, c] {
220 Headers &responseHeaders = c->response()->headers();
221 const QList<QNetworkReply::RawHeaderPair> &headers = reply->rawHeaderPairs();
222 for (const QNetworkReply::RawHeaderPair &pair : headers) {
223 responseHeaders.pushHeader(pair.first, pair.second);
224 }
225 c->response()->setStatus(
226 quint16(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toUInt()));
227 c->response()->setBody(reply);
228 });
229}
Helper class for asynchronous processing.
Definition async.h:16
The Cutelyst Context.
Definition context.h:42
Request * request
Definition context.h:71
Response * response() const noexcept
Definition context.cpp:98
Container for HTTP headers.
Definition headers.h:24
QVector< HeaderKeyValue > data() const
Definition headers.h:419
void pushHeader(const QByteArray &key, const QByteArray &value)
Definition headers.cpp:461
A request.
Definition request.h:42
Headers headers() const noexcept
Definition request.cpp:313
QIODevice * body() const noexcept
Definition request.cpp:180
void setStatus(quint16 status) noexcept
Definition response.cpp:73
void setBody(QIODevice *body)
Definition response.cpp:104
Headers & headers() noexcept
Send network requests to other endpoints.
Definition useragent.h:45
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * sendCustomRequestJsonObject(const QNetworkRequest &request, const QByteArray &verb, const QJsonObject &object)
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * putJson(const QNetworkRequest &request, const QJsonDocument &doc)
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data=nullptr)
Definition useragent.cpp:66
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * forwardRequestResponse(Context *c, const QUrl &destination)
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * postJsonArray(const QNetworkRequest &request, const QJsonArray &array)
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * head(const QNetworkRequest &request)
Definition useragent.cpp:30
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * get(const QNetworkRequest &request)
Definition useragent.cpp:35
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * forwardRequest(Request *request, const QUrl &destination)
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * postJsonObject(const QNetworkRequest &request, const QJsonObject &object)
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * putJsonArray(const QNetworkRequest &request, const QJsonArray &array)
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkAccessManager * networkAccessManager()
Definition useragent.cpp:23
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * sendCustomRequestJson(const QNetworkRequest &request, const QByteArray &verb, const QJsonDocument &doc)
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * put(const QNetworkRequest &request, QIODevice *data)
Definition useragent.cpp:50
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * postJson(const QNetworkRequest &request, const QJsonDocument &doc)
Definition useragent.cpp:95
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * deleteResource(const QNetworkRequest &request)
Definition useragent.cpp:60
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * post(const QNetworkRequest &request, QIODevice *data)
Definition useragent.cpp:40
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * sendCustomRequestJsonArray(const QNetworkRequest &request, const QByteArray &verb, const QJsonArray &array)
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * putJsonObject(const QNetworkRequest &request, const QJsonObject &object)
CUTELYST_PLUGIN_USERAGENT_EXPORT void forwardAsync(Context *c, const QUrl &destination)
The Cutelyst namespace holds all public Cutelyst API.