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