cutelyst  4.4.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 
19 using namespace Cutelyst;
20 
21 Q_LOGGING_CATEGORY(C_USERAGENT, "cutelyst.useragent", QtWarningMsg)
22 
23 static thread_local QNetworkAccessManager m_instance;
24 
26 {
27  return &m_instance;
28 }
29 
31 {
32  return m_instance.head(request);
33 }
34 
36 {
37  return m_instance.get(request);
38 }
39 
41 {
42  return m_instance.post(request, data);
43 }
44 
45 QNetworkReply *UA::post(const QNetworkRequest &request, const QByteArray &data)
46 {
47  return m_instance.post(request, data);
48 }
49 
51 {
52  return m_instance.put(request, data);
53 }
54 
55 QNetworkReply *UA::put(const QNetworkRequest &request, const QByteArray &data)
56 {
57  return m_instance.put(request, data);
58 }
59 
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 
72  const QByteArray &verb,
73  const QByteArray &data)
74 {
75  return m_instance.sendCustomRequest(request, verb, data);
76 }
77 
79 {
80  return m_instance.post(request, multiPart);
81 }
82 
84 {
85  return m_instance.post(request, multiPart);
86 }
87 
89  const QByteArray &verb,
90  QHttpMultiPart *multiPart)
91 {
92  return m_instance.sendCustomRequest(request, verb, multiPart);
93 }
94 
96 {
97  QNetworkRequest jsonRequest(request);
99  QByteArrayLiteral("application/json"));
100  return m_instance.post(jsonRequest, doc.toJson(QJsonDocument::Compact));
101 }
102 
104 {
105  QNetworkRequest jsonRequest(request);
107  QByteArrayLiteral("application/json"));
108  return m_instance.put(jsonRequest, doc.toJson(QJsonDocument::Compact));
109 }
110 
112  const QByteArray &verb,
113  const QJsonDocument &doc)
114 {
115  QNetworkRequest jsonRequest(request);
117  QByteArrayLiteral("application/json"));
118  return UA::sendCustomRequest(jsonRequest, verb, doc.toJson(QJsonDocument::Compact));
119 }
120 
122 {
123  QNetworkRequest jsonRequest(request);
125  QByteArrayLiteral("application/json"));
126  return m_instance.post(jsonRequest, QJsonDocument(object).toJson(QJsonDocument::Compact));
127 }
128 
130 {
131  QNetworkRequest jsonRequest(request);
133  QByteArrayLiteral("application/json"));
134  return m_instance.put(jsonRequest, QJsonDocument(object).toJson(QJsonDocument::Compact));
135 }
136 
138  const QByteArray &verb,
139  const QJsonObject &object)
140 {
141  QNetworkRequest jsonRequest(request);
143  QByteArrayLiteral("application/json"));
144  return UA::sendCustomRequest(
145  jsonRequest, verb, QJsonDocument(object).toJson(QJsonDocument::Compact));
146 }
147 
149 {
150  QNetworkRequest jsonRequest(request);
152  QByteArrayLiteral("application/json"));
153  return m_instance.post(jsonRequest, QJsonDocument(array).toJson(QJsonDocument::Compact));
154 }
155 
157 {
158  QNetworkRequest jsonRequest(request);
160  QByteArrayLiteral("application/json"));
161  return m_instance.put(jsonRequest, QJsonDocument(array).toJson(QJsonDocument::Compact));
162 }
163 
165  const QByteArray &verb,
166  const QJsonArray &array)
167 {
168  QNetworkRequest jsonRequest(request);
170  QByteArrayLiteral("application/json"));
171  return UA::sendCustomRequest(
172  jsonRequest, verb, QJsonDocument(array).toJson(QJsonDocument::Compact));
173 }
174 
175 QNetworkReply *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.begin();
187  while (it != headersData.end()) {
188  proxyReq.setRawHeader(it->key, it->value);
189  ++it;
190  }
191 
192  return m_instance.sendCustomRequest(proxyReq, request->method(), request->body());
193 }
194 
196 {
197  QNetworkReply *reply = forwardRequest(c->request(), destination);
198  QObject::connect(reply, &QNetworkReply::finished, c, [=] {
199  Headers &responseHeaders = c->response()->headers();
200  const QList<QNetworkReply::RawHeaderPair> &headers = reply->rawHeaderPairs();
201  for (const QNetworkReply::RawHeaderPair &pair : headers) {
202  responseHeaders.pushHeader(pair.first, pair.second);
203  }
204  c->response()->setStatus(
206  c->response()->setBody(reply);
207  });
208  return reply;
209 }
210 
211 void UA::forwardAsync(Context *c, const QUrl &destination)
212 {
213  QNetworkReply *reply = forwardRequest(c->request(), destination);
214  QObject::connect(reply, &QNetworkReply::finished, c, [=] {
215  Headers &responseHeaders = c->response()->headers();
216  const QList<QNetworkReply::RawHeaderPair> &headers = reply->rawHeaderPairs();
217  for (const QNetworkReply::RawHeaderPair &pair : headers) {
218  responseHeaders.pushHeader(pair.first, pair.second);
219  }
220  c->response()->setStatus(
222  c->response()->setBody(reply);
223  c->attachAsync();
224  });
225  c->detachAsync();
226 }
The Cutelyst Context.
Definition: context.h:42
Request * request
Definition: context.h:71
void attachAsync()
Definition: context.cpp:355
void detachAsync() noexcept
Definition: context.cpp:349
Response * response() const noexcept
Definition: context.cpp:97
Container for HTTP headers.
Definition: headers.h:24
void pushHeader(const QByteArray &key, const QByteArray &value)
Definition: headers.cpp:460
QVector< HeaderKeyValue > data() const
Definition: headers.h:419
A request.
Definition: request.h:42
Headers headers() const noexcept
Definition: request.cpp:312
QIODevice * body() const noexcept
Definition: request.cpp:179
void setBody(QIODevice *body)
Definition: response.cpp:103
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * sendCustomRequestJsonObject(const QNetworkRequest &request, const QByteArray &verb, const QJsonObject &object)
Definition: useragent.cpp:137
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * putJson(const QNetworkRequest &request, const QJsonDocument &doc)
Definition: useragent.cpp:103
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)
Definition: useragent.cpp:195
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * postJsonArray(const QNetworkRequest &request, const QJsonArray &array)
Definition: useragent.cpp:148
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)
Definition: useragent.cpp:175
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * postJsonObject(const QNetworkRequest &request, const QJsonObject &object)
Definition: useragent.cpp:121
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * putJsonArray(const QNetworkRequest &request, const QJsonArray &array)
Definition: useragent.cpp:156
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkAccessManager * networkAccessManager()
Definition: useragent.cpp:25
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * sendCustomRequestJson(const QNetworkRequest &request, const QByteArray &verb, const QJsonDocument &doc)
Definition: useragent.cpp:111
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)
Definition: useragent.cpp:164
CUTELYST_PLUGIN_USERAGENT_EXPORT QNetworkReply * putJsonObject(const QNetworkRequest &request, const QJsonObject &object)
Definition: useragent.cpp:129
CUTELYST_PLUGIN_USERAGENT_EXPORT void forwardAsync(Context *c, const QUrl &destination)
Definition: useragent.cpp:211
The Cutelyst namespace holds all public Cutelyst API.
QByteArray toJson(QJsonDocument::JsonFormat format) const const
QNetworkReply * deleteResource(const QNetworkRequest &request)
QNetworkReply * get(const QNetworkRequest &request)
QNetworkReply * head(const QNetworkRequest &request)
QNetworkReply * post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
QNetworkReply * put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
QNetworkReply * sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QHttpMultiPart *multiPart)
typedef RawHeaderPair
QVariant attribute(QNetworkRequest::Attribute code) const const
const QList< QNetworkReply::RawHeaderPair > & rawHeaderPairs() const const
void setHeader(QNetworkRequest::KnownHeaders header, const QVariant &value)
void setRawHeader(const QByteArray &headerName, const QByteArray &headerValue)
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString host(QUrl::ComponentFormattingOptions options) const const
int port(int defaultPort) const const
QString scheme() const const
void setHost(const QString &host, QUrl::ParsingMode mode)
void setPort(int port)
void setScheme(const QString &scheme)
uint toUInt(bool *ok) const const