Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qhttpnetworkrequest.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6#include "private/qnoncontiguousbytedevice_p.h"
7
8#include <QtCore/private/qtools_p.h>
9
11
13
14QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,
15 QHttpNetworkRequest::Priority pri, const QUrl &newUrl)
16 : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(nullptr),
17 autoDecompress(false), pipeliningAllowed(false), http2Allowed(true),
18 http2Direct(false), withCredentials(true), preConnect(false), redirectCount(0),
19 redirectPolicy(QNetworkRequest::ManualRedirectPolicy)
20{
21}
22
44
48
50{
51 return QHttpNetworkHeaderPrivate::operator==(other)
52 && (operation == other.operation)
53 && (fullLocalServerName == other.fullLocalServerName)
54 && (priority == other.priority)
55 && (uploadByteDevice == other.uploadByteDevice)
56 && (autoDecompress == other.autoDecompress)
57 && (pipeliningAllowed == other.pipeliningAllowed)
58 && (http2Allowed == other.http2Allowed)
59 && (http2Direct == other.http2Direct)
60 && (h2cAllowed == other.h2cAllowed)
61 // we do not clear the customVerb in setOperation
62 && (operation != QHttpNetworkRequest::Custom || (customVerb == other.customVerb))
63 && (withCredentials == other.withCredentials)
64 && (ssl == other.ssl)
65 && (preConnect == other.preConnect)
66 && (redirectPolicy == other.redirectPolicy)
67 && (peerVerifyName == other.peerVerifyName)
68 && (needResendWithCredentials == other.needResendWithCredentials)
69 ;
70}
71
72QByteArray QHttpNetworkRequest::methodName() const
73{
74 switch (d->operation) {
75 case QHttpNetworkRequest::Get:
76 return "GET";
77 case QHttpNetworkRequest::Head:
78 return "HEAD";
79 case QHttpNetworkRequest::Post:
80 return "POST";
81 case QHttpNetworkRequest::Options:
82 return "OPTIONS";
83 case QHttpNetworkRequest::Put:
84 return "PUT";
85 case QHttpNetworkRequest::Delete:
86 return "DELETE";
87 case QHttpNetworkRequest::Trace:
88 return "TRACE";
89 case QHttpNetworkRequest::Connect:
90 return "CONNECT";
91 case QHttpNetworkRequest::Custom:
92 return d->customVerb;
93 default:
94 break;
95 }
96 return QByteArray();
97}
98
99QByteArray QHttpNetworkRequest::uri(bool throughProxy) const
100{
101 QUrl::FormattingOptions format(QUrl::RemoveFragment | QUrl::RemoveUserInfo | QUrl::FullyEncoded);
102
103 // for POST, query data is sent as content
104 if (d->operation == QHttpNetworkRequest::Post && !d->uploadByteDevice)
105 format |= QUrl::RemoveQuery;
106 // for requests through proxy, the Request-URI contains full url
107 if (!throughProxy)
108 format |= QUrl::RemoveScheme | QUrl::RemoveAuthority;
109 QUrl copy = d->url;
110 if (copy.path().isEmpty())
111 copy.setPath(QStringLiteral("/"));
112 else
113 format |= QUrl::NormalizePathSegments;
114 QByteArray uri = copy.toEncoded(format);
115 return uri;
116}
117
118QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request, bool throughProxy)
119{
120 const QHttpHeaders headers = request.header();
121 QByteArray ba;
122 ba.reserve(40 + headers.size() * 25); // very rough lower bound estimation
123
124 ba += request.methodName();
125 ba += ' ';
126 ba += request.uri(throughProxy);
127
128 ba += " HTTP/";
129 ba += QByteArray::number(request.majorVersion());
130 ba += '.';
131 ba += QByteArray::number(request.minorVersion());
132 ba += "\r\n";
133
134 constexpr auto titlecase = [](QByteArrayView name) {
135 std::string n;
136 n.reserve(size_t(name.size()));
137 bool toUpperNext = true;
138 for (char c : name) {
139 n += toUpperNext ? QtMiscUtils::toAsciiUpper(c) : c;
140 toUpperNext = c == '-';
141 }
142 return n;
143 };
144
145 for (qsizetype i = 0; i < headers.size(); ++i) {
146 ba += titlecase(headers.nameAt(i));
147 ba += ": ";
148 ba += headers.valueAt(i);
149 ba += "\r\n";
150 }
151 if (request.d->operation == QHttpNetworkRequest::Post) {
152 // add content type, if not set in the request
153 if (request.headerField("content-type").isEmpty() && ((request.d->uploadByteDevice && request.d->uploadByteDevice->size() > 0) || request.d->url.hasQuery())) {
154 //Content-Type is mandatory. We can't say anything about the encoding, but x-www-form-urlencoded is the most likely to work.
155 //This warning indicates a bug in application code not setting a required header.
156 //Note that if using QHttpMultipart, the content-type is set in QNetworkAccessManagerPrivate::prepareMultipart already
157 qWarning("content-type missing in HTTP POST, defaulting to application/x-www-form-urlencoded. Use QNetworkRequest::setHeader() to fix this problem.");
158 ba += "Content-Type: application/x-www-form-urlencoded\r\n";
159 }
160 if (!request.d->uploadByteDevice && request.d->url.hasQuery()) {
161 QByteArray query = request.d->url.query(QUrl::FullyEncoded).toLatin1();
162 ba += "Content-Length: ";
163 ba += QByteArray::number(query.size());
164 ba += "\r\n\r\n";
165 ba += query;
166 } else {
167 ba += "\r\n";
168 }
169 } else {
170 ba += "\r\n";
171 }
172 return ba;
173}
174
175
176// QHttpNetworkRequest
177
178QHttpNetworkRequest::QHttpNetworkRequest(const QUrl &url, Operation operation, Priority priority)
179 : d(new QHttpNetworkRequestPrivate(operation, priority, url))
180{
181}
182
183QHttpNetworkRequest::QHttpNetworkRequest(const QHttpNetworkRequest &other)
184 : QHttpNetworkHeader(other), d(other.d)
185{
186}
187
188QHttpNetworkRequest::~QHttpNetworkRequest()
189{
190}
191
192QUrl QHttpNetworkRequest::url() const
193{
194 return d->url;
195}
196void QHttpNetworkRequest::setUrl(const QUrl &url)
197{
198 d->url = url;
199}
200
201bool QHttpNetworkRequest::isSsl() const
202{
203 return d->ssl;
204}
205void QHttpNetworkRequest::setSsl(bool s)
206{
207 d->ssl = s;
208}
209
210bool QHttpNetworkRequest::isPreConnect() const
211{
212 return d->preConnect;
213}
214void QHttpNetworkRequest::setPreConnect(bool preConnect)
215{
216 d->preConnect = preConnect;
217}
218
219bool QHttpNetworkRequest::isFollowRedirects() const
220{
221 return d->redirectPolicy != QNetworkRequest::ManualRedirectPolicy;
222}
223
224void QHttpNetworkRequest::setRedirectPolicy(QNetworkRequest::RedirectPolicy policy)
225{
226 d->redirectPolicy = policy;
227}
228
229QNetworkRequest::RedirectPolicy QHttpNetworkRequest::redirectPolicy() const
230{
231 return d->redirectPolicy;
232}
233
234int QHttpNetworkRequest::redirectCount() const
235{
236 return d->redirectCount;
237}
238
239void QHttpNetworkRequest::setRedirectCount(int count)
240{
241 d->redirectCount = count;
242}
243
244qint64 QHttpNetworkRequest::contentLength() const
245{
246 return d->contentLength();
247}
248
249void QHttpNetworkRequest::setContentLength(qint64 length)
250{
251 d->setContentLength(length);
252}
253
254QHttpHeaders QHttpNetworkRequest::header() const
255{
256 return d->parser.headers();
257}
258
259QByteArray QHttpNetworkRequest::headerField(QByteArrayView name, const QByteArray &defaultValue) const
260{
261 return d->headerField(name, defaultValue);
262}
263
264void QHttpNetworkRequest::setHeaderField(const QByteArray &name, const QByteArray &data)
265{
266 d->setHeaderField(name, data);
267}
268
269void QHttpNetworkRequest::prependHeaderField(const QByteArray &name, const QByteArray &data)
270{
271 d->prependHeaderField(name, data);
272}
273
274void QHttpNetworkRequest::clearHeaders()
275{
276 d->clearHeaders();
277}
278
279QHttpNetworkRequest &QHttpNetworkRequest::operator=(const QHttpNetworkRequest &other)
280{
281 QHttpNetworkHeader::operator=(other);
282 d = other.d;
283 return *this;
284}
285
286bool QHttpNetworkRequest::operator==(const QHttpNetworkRequest &other) const
287{
288 return d->operator==(*other.d);
289}
290
291QHttpNetworkRequest::Operation QHttpNetworkRequest::operation() const
292{
293 return d->operation;
294}
295
296void QHttpNetworkRequest::setOperation(Operation operation)
297{
298 d->operation = operation;
299}
300
301QByteArray QHttpNetworkRequest::customVerb() const
302{
303 return d->customVerb;
304}
305
306void QHttpNetworkRequest::setCustomVerb(const QByteArray &customVerb)
307{
308 d->customVerb = customVerb;
309}
310
311QHttpNetworkRequest::Priority QHttpNetworkRequest::priority() const
312{
313 return d->priority;
314}
315
316void QHttpNetworkRequest::setPriority(Priority priority)
317{
318 d->priority = priority;
319}
320
321bool QHttpNetworkRequest::isPipeliningAllowed() const
322{
323 return d->pipeliningAllowed;
324}
325
326void QHttpNetworkRequest::setPipeliningAllowed(bool b)
327{
328 d->pipeliningAllowed = b;
329}
330
331bool QHttpNetworkRequest::isHTTP2Allowed() const
332{
333 return d->http2Allowed;
334}
335
336void QHttpNetworkRequest::setHTTP2Allowed(bool b)
337{
338 d->http2Allowed = b;
339}
340
341bool QHttpNetworkRequest::isHTTP2Direct() const
342{
343 return d->http2Direct;
344}
345
346void QHttpNetworkRequest::setHTTP2Direct(bool b)
347{
348 d->http2Direct = b;
349}
350
351bool QHttpNetworkRequest::isH2cAllowed() const
352{
353 return d->h2cAllowed;
354}
355
356void QHttpNetworkRequest::setH2cAllowed(bool b)
357{
358 d->h2cAllowed = b;
359}
360
361bool QHttpNetworkRequest::withCredentials() const
362{
363 return d->withCredentials;
364}
365
366void QHttpNetworkRequest::setWithCredentials(bool b)
367{
368 d->withCredentials = b;
369}
370
371void QHttpNetworkRequest::setUploadByteDevice(QNonContiguousByteDevice *bd)
372{
373 d->uploadByteDevice = bd;
374}
375
376QNonContiguousByteDevice* QHttpNetworkRequest::uploadByteDevice() const
377{
378 return d->uploadByteDevice;
379}
380
381int QHttpNetworkRequest::majorVersion() const
382{
383 return 1;
384}
385
386int QHttpNetworkRequest::minorVersion() const
387{
388 return 1;
389}
390
391QString QHttpNetworkRequest::peerVerifyName() const
392{
393 return d->peerVerifyName;
394}
395
396void QHttpNetworkRequest::setPeerVerifyName(const QString &peerName)
397{
398 d->peerVerifyName = peerName;
399}
400
401QString QHttpNetworkRequest::fullLocalServerName() const
402{
403 return d->fullLocalServerName;
404}
405
406void QHttpNetworkRequest::setFullLocalServerName(const QString &fullServerName)
407{
408 d->fullLocalServerName = fullServerName;
409}
410
411bool QHttpNetworkRequest::methodIsIdempotent() const
412{
413 using Op = Operation;
414 constexpr auto knownSafe = std::array{ Op::Get, Op::Head, Op::Put, Op::Trace, Op::Options };
415 return std::any_of(knownSafe.begin(), knownSafe.end(),
416 [currentOp = d->operation](auto op) { return op == currentOp; });
417}
418
419QT_END_NAMESPACE
bool operator==(const QHttpNetworkRequestPrivate &other) const
QNonContiguousByteDevice * uploadByteDevice
QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate &other)
Combined button and popup list for selecting options.
#define QT_IMPL_METATYPE_EXTERN(TYPE)
Definition qmetatype.h:1372