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

Provided by KDAB

Privacy Policy
Start learning QML with our Intro Training
Find out more

source code of qtbase/src/network/access/qhttpnetworkrequest.cpp