cutelyst  3.7.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/Engine>
8 #include <Cutelyst/Context>
9 #include <Cutelyst/Request>
10 #include <Cutelyst/Response>
11 
12 #include <QHostAddress>
13 #include <QLoggingCategory>
14 #include <QNetworkAccessManager>
15 
16 #include <QBuffer>
17 #include <QHttpMultiPart>
18 
19 #include <QJsonDocument>
20 
21 using namespace Cutelyst;
22 
23 Q_LOGGING_CATEGORY(C_USERAGENT, "cutelyst.useragent", QtInfoMsg)
24 
25 static thread_local QNetworkAccessManager m_instance;
26 
27 QNetworkAccessManager *Cutelyst::UA::networkAccessManager()
28 {
29  return &m_instance;
30 }
31 
32 QNetworkReply *UA::head(const QNetworkRequest &request)
33 {
34  return m_instance.head(request);
35 }
36 
37 QNetworkReply *UA::get(const QNetworkRequest &request)
38 {
39  return m_instance.get(request);
40 }
41 
42 QNetworkReply *UA::post(const QNetworkRequest &request, QIODevice *data)
43 {
44  return m_instance.post(request, data);
45 }
46 
47 QNetworkReply *UA::post(const QNetworkRequest &request, const QByteArray &data)
48 {
49  return m_instance.post(request, data);
50 }
51 
52 QNetworkReply *UA::put(const QNetworkRequest &request, QIODevice *data)
53 {
54  return m_instance.put(request, data);
55 }
56 
57 QNetworkReply *UA::put(const QNetworkRequest &request, const QByteArray &data)
58 {
59  return m_instance.put(request, data);
60 }
61 
62 QNetworkReply *UA::deleteResource(const QNetworkRequest &request)
63 {
64  return m_instance.deleteResource(request);
65 }
66 
67 QNetworkReply *UA::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
68 {
69  return m_instance.sendCustomRequest(request, verb, data);
70 }
71 
72 QNetworkReply *UA::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, const QByteArray &data)
73 {
74  return m_instance.sendCustomRequest(request, verb, data);
75 }
76 
77 QNetworkReply *UA::post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
78 {
79  return m_instance.post(request, multiPart);
80 }
81 
82 QNetworkReply *UA::put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
83 {
84  return m_instance.post(request, multiPart);
85 }
86 
87 QNetworkReply *UA::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QHttpMultiPart *multiPart)
88 {
89  return m_instance.sendCustomRequest(request, verb, multiPart);
90 }
91 
92 QNetworkReply *UA::postJson(const QNetworkRequest &request, const QJsonDocument &doc)
93 {
94  QNetworkRequest jsonRequest(request);
95  jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
96  return m_instance.post(jsonRequest, doc.toJson(QJsonDocument::Compact));
97 }
98 
99 QNetworkReply *UA::putJson(const QNetworkRequest &request, const QJsonDocument &doc)
100 {
101  QNetworkRequest jsonRequest(request);
102  jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
103  return m_instance.put(jsonRequest, doc.toJson(QJsonDocument::Compact));
104 }
105 
106 QNetworkReply *UA::sendCustomRequestJson(const QNetworkRequest &request, const QByteArray &verb, const QJsonDocument &doc)
107 {
108  QNetworkRequest jsonRequest(request);
109  jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
110  return UA::sendCustomRequest(jsonRequest, verb, doc.toJson(QJsonDocument::Compact));
111 }
112 
113 QNetworkReply *UA::postJsonObject(const QNetworkRequest &request, const QJsonObject &obj)
114 {
115  QNetworkRequest jsonRequest(request);
116  jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
117  return m_instance.post(jsonRequest, QJsonDocument(obj).toJson(QJsonDocument::Compact));
118 }
119 
120 QNetworkReply *UA::putJsonObject(const QNetworkRequest &request, const QJsonObject &obj)
121 {
122  QNetworkRequest jsonRequest(request);
123  jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
124  return m_instance.put(jsonRequest, QJsonDocument(obj).toJson(QJsonDocument::Compact));
125 }
126 
127 QNetworkReply *UA::sendCustomRequestJsonObject(const QNetworkRequest &request, const QByteArray &verb, const QJsonObject &obj)
128 {
129  QNetworkRequest jsonRequest(request);
130  jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
131  return UA::sendCustomRequest(jsonRequest, verb, QJsonDocument(obj).toJson(QJsonDocument::Compact));
132 }
133 
134 QNetworkReply *UA::postJsonArray(const QNetworkRequest &request, const QJsonArray &array)
135 {
136  QNetworkRequest jsonRequest(request);
137  jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
138  return m_instance.post(jsonRequest, QJsonDocument(array).toJson(QJsonDocument::Compact));
139 }
140 
141 QNetworkReply *UA::putJsonArray(const QNetworkRequest &request, const QJsonArray &array)
142 {
143  QNetworkRequest jsonRequest(request);
144  jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
145  return m_instance.put(jsonRequest, QJsonDocument(array).toJson(QJsonDocument::Compact));
146 }
147 
148 QNetworkReply *UA::sendCustomRequestJsonArray(const QNetworkRequest &request, const QByteArray &verb, const QJsonArray &array)
149 {
150  QNetworkRequest jsonRequest(request);
151  jsonRequest.setHeader(QNetworkRequest::ContentTypeHeader, QByteArrayLiteral("application/json"));
152  return UA::sendCustomRequest(jsonRequest, verb, QJsonDocument(array).toJson(QJsonDocument::Compact));
153 }
154 
155 QNetworkReply *UA::forwardRequest(Request *request, const QUrl &destination)
156 {
157  QUrl dest(request->uri());
158  dest.setHost(destination.host());
159  dest.setPort(destination.port());
160  dest.setScheme(destination.scheme());
161 
162  QNetworkRequest proxyReq(dest);
163 
164  const Headers reqHeaders = request->headers();
165  const auto headersData = reqHeaders.data();
166  auto it = headersData.constBegin();
167  while (it != headersData.constEnd()) {
168  proxyReq.setRawHeader(Cutelyst::Engine::camelCaseHeader(it.key()).toLatin1(), it.value().toLatin1());
169  ++it;
170  }
171 
172  return m_instance.sendCustomRequest(proxyReq, request->method().toLatin1(), request->body());
173 }
174 
175 QNetworkReply *UA::forwardRequestResponse(Context *c, const QUrl &destination)
176 {
177  QNetworkReply *reply = forwardRequest(c->request(), destination);
178  QObject::connect(reply, &QNetworkReply::finished, c, [=] {
179  Headers &responseHeaders = c->response()->headers();
180  const QList<QNetworkReply::RawHeaderPair> &headers = reply->rawHeaderPairs();
181  for (const QNetworkReply::RawHeaderPair &pair : headers) {
182  responseHeaders.setHeader(QString::fromLatin1(pair.first), QString::fromLatin1(pair.second));
183  }
184  c->response()->setStatus(quint16(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toUInt()));
185  c->response()->setBody(reply);
186  });
187  return reply;
188 }
189 
190 void UA::forwardAsync(Context *c, const QUrl &destination)
191 {
192  QNetworkReply *reply = forwardRequest(c->request(), destination);
193  QObject::connect(reply, &QNetworkReply::finished, c, [=] {
194  Headers &responseHeaders = c->response()->headers();
195  const QList<QNetworkReply::RawHeaderPair> &headers = reply->rawHeaderPairs();
196  for (const QNetworkReply::RawHeaderPair &pair : headers) {
197  responseHeaders.setHeader(QString::fromLatin1(pair.first), QString::fromLatin1(pair.second));
198  }
199  c->response()->setStatus(quint16(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toUInt()));
200  c->response()->setBody(reply);
201  c->attachAsync();
202  });
203  c->detachAsync();
204 }
The Cutelyst Context.
Definition: context.h:39
void attachAsync()
attachAsync
Definition: context.cpp:355
void detachAsync() noexcept
Definition: context.cpp:349
Response * response() const noexcept
Definition: context.cpp:97
static QString camelCaseHeader(const QString &headerKey)
Definition: engine.h:103
QMultiHash< QString, QString > data() const
Definition: headers.h:377
void setHeader(const QString &field, const QString &value)
Definition: headers.cpp:400
Headers headers() const noexcept
Definition: request.cpp:308
QIODevice * body() const
Definition: request.cpp:179
void setBody(QIODevice *body)
Definition: response.cpp:101
The Cutelyst namespace holds all public Cutelyst API.
Definition: Mainpage.dox:8