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

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