1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://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 http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://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 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qhttpnetworkrequest_p.h"
43 #include "private/qnoncontiguousbytedevice_p.h"
44
45 #ifndef QT_NO_HTTP
46
47 QT_BEGIN_NAMESPACE
48
QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,QHttpNetworkRequest::Priority pri,const QUrl & newUrl)49 QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(QHttpNetworkRequest::Operation op,
50 QHttpNetworkRequest::Priority pri, const QUrl &newUrl)
51 : QHttpNetworkHeaderPrivate(newUrl), operation(op), priority(pri), uploadByteDevice(0),
52 autoDecompress(false), pipeliningAllowed(false), withCredentials(true)
53 {
54 }
55
QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate & other)56 QHttpNetworkRequestPrivate::QHttpNetworkRequestPrivate(const QHttpNetworkRequestPrivate &other)
57 : QHttpNetworkHeaderPrivate(other)
58 {
59 operation = other.operation;
60 priority = other.priority;
61 uploadByteDevice = other.uploadByteDevice;
62 autoDecompress = other.autoDecompress;
63 pipeliningAllowed = other.pipeliningAllowed;
64 customVerb = other.customVerb;
65 withCredentials = other.withCredentials;
66 ssl = other.ssl;
67 }
68
~QHttpNetworkRequestPrivate()69 QHttpNetworkRequestPrivate::~QHttpNetworkRequestPrivate()
70 {
71 }
72
operator ==(const QHttpNetworkRequestPrivate & other) const73 bool QHttpNetworkRequestPrivate::operator==(const QHttpNetworkRequestPrivate &other) const
74 {
75 return QHttpNetworkHeaderPrivate::operator==(other)
76 && (operation == other.operation)
77 && (ssl == other.ssl)
78 && (uploadByteDevice == other.uploadByteDevice);
79 }
80
methodName() const81 QByteArray QHttpNetworkRequestPrivate::methodName() const
82 {
83 switch (operation) {
84 case QHttpNetworkRequest::Get:
85 return "GET";
86 break;
87 case QHttpNetworkRequest::Head:
88 return "HEAD";
89 break;
90 case QHttpNetworkRequest::Post:
91 return "POST";
92 break;
93 case QHttpNetworkRequest::Options:
94 return "OPTIONS";
95 break;
96 case QHttpNetworkRequest::Put:
97 return "PUT";
98 break;
99 case QHttpNetworkRequest::Delete:
100 return "DELETE";
101 break;
102 case QHttpNetworkRequest::Trace:
103 return "TRACE";
104 break;
105 case QHttpNetworkRequest::Connect:
106 return "CONNECT";
107 break;
108 case QHttpNetworkRequest::Custom:
109 return customVerb;
110 break;
111 default:
112 break;
113 }
114 return QByteArray();
115 }
116
uri(bool throughProxy) const117 QByteArray QHttpNetworkRequestPrivate::uri(bool throughProxy) const
118 {
119 QUrl::FormattingOptions format(QUrl::RemoveFragment);
120
121 // for POST, query data is send as content
122 if (operation == QHttpNetworkRequest::Post && !uploadByteDevice)
123 format |= QUrl::RemoveQuery;
124 // for requests through proxy, the Request-URI contains full url
125 if (throughProxy)
126 format |= QUrl::RemoveUserInfo;
127 else
128 format |= QUrl::RemoveScheme | QUrl::RemoveAuthority;
129 QByteArray uri = url.toEncoded(format);
130 if (uri.isEmpty() || (throughProxy && url.path().isEmpty()))
131 uri += '/';
132 return uri;
133 }
134
header(const QHttpNetworkRequest & request,bool throughProxy)135 QByteArray QHttpNetworkRequestPrivate::header(const QHttpNetworkRequest &request, bool throughProxy)
136 {
137 QList<QPair<QByteArray, QByteArray> > fields = request.header();
138 QByteArray ba;
139 ba.reserve(40 + fields.length()*25); // very rough lower bound estimation
140
141 ba += request.d->methodName();
142 ba += ' ';
143 ba += request.d->uri(throughProxy);
144
145 ba += " HTTP/";
146 ba += QByteArray::number(request.majorVersion());
147 ba += '.';
148 ba += QByteArray::number(request.minorVersion());
149 ba += "\r\n";
150
151 QList<QPair<QByteArray, QByteArray> >::const_iterator it = fields.constBegin();
152 QList<QPair<QByteArray, QByteArray> >::const_iterator endIt = fields.constEnd();
153 for (; it != endIt; ++it) {
154 ba += it->first;
155 ba += ": ";
156 ba += it->second;
157 ba += "\r\n";
158 }
159 if (request.d->operation == QHttpNetworkRequest::Post) {
160 // add content type, if not set in the request
161 if (request.headerField("content-type").isEmpty()) {
162 //Content-Type is mandatory. We can't say anything about the encoding, but x-www-form-urlencoded is the most likely to work.
163 //This warning indicates a bug in application code not setting a required header.
164 //Note that if using QHttpMultipart, the content-type is set in QNetworkAccessManagerPrivate::prepareMultipart already
165 qWarning("content-type missing in HTTP POST, defaulting to application/x-www-form-urlencoded. Use QNetworkRequest::setHeader() to fix this problem.");
166 ba += "Content-Type: application/x-www-form-urlencoded\r\n";
167 }
168 if (!request.d->uploadByteDevice && request.d->url.hasQuery()) {
169 QByteArray query = request.d->url.encodedQuery();
170 ba += "Content-Length: ";
171 ba += QByteArray::number(query.size());
172 ba += "\r\n\r\n";
173 ba += query;
174 } else {
175 ba += "\r\n";
176 }
177 } else {
178 ba += "\r\n";
179 }
180 return ba;
181 }
182
183
184 // QHttpNetworkRequest
185
QHttpNetworkRequest(const QUrl & url,Operation operation,Priority priority)186 QHttpNetworkRequest::QHttpNetworkRequest(const QUrl &url, Operation operation, Priority priority)
187 : d(new QHttpNetworkRequestPrivate(operation, priority, url))
188 {
189 }
190
QHttpNetworkRequest(const QHttpNetworkRequest & other)191 QHttpNetworkRequest::QHttpNetworkRequest(const QHttpNetworkRequest &other)
192 : QHttpNetworkHeader(other), d(other.d)
193 {
194 }
195
~QHttpNetworkRequest()196 QHttpNetworkRequest::~QHttpNetworkRequest()
197 {
198 }
199
url() const200 QUrl QHttpNetworkRequest::url() const
201 {
202 return d->url;
203 }
setUrl(const QUrl & url)204 void QHttpNetworkRequest::setUrl(const QUrl &url)
205 {
206 d->url = url;
207 }
208
isSsl() const209 bool QHttpNetworkRequest::isSsl() const
210 {
211 return d->ssl;
212 }
setSsl(bool s)213 void QHttpNetworkRequest::setSsl(bool s)
214 {
215 d->ssl = s;
216 }
217
contentLength() const218 qint64 QHttpNetworkRequest::contentLength() const
219 {
220 return d->contentLength();
221 }
222
setContentLength(qint64 length)223 void QHttpNetworkRequest::setContentLength(qint64 length)
224 {
225 d->setContentLength(length);
226 }
227
header() const228 QList<QPair<QByteArray, QByteArray> > QHttpNetworkRequest::header() const
229 {
230 return d->fields;
231 }
232
headerField(const QByteArray & name,const QByteArray & defaultValue) const233 QByteArray QHttpNetworkRequest::headerField(const QByteArray &name, const QByteArray &defaultValue) const
234 {
235 return d->headerField(name, defaultValue);
236 }
237
setHeaderField(const QByteArray & name,const QByteArray & data)238 void QHttpNetworkRequest::setHeaderField(const QByteArray &name, const QByteArray &data)
239 {
240 d->setHeaderField(name, data);
241 }
242
operator =(const QHttpNetworkRequest & other)243 QHttpNetworkRequest &QHttpNetworkRequest::operator=(const QHttpNetworkRequest &other)
244 {
245 d = other.d;
246 return *this;
247 }
248
operator ==(const QHttpNetworkRequest & other) const249 bool QHttpNetworkRequest::operator==(const QHttpNetworkRequest &other) const
250 {
251 return d->operator==(*other.d);
252 }
253
operation() const254 QHttpNetworkRequest::Operation QHttpNetworkRequest::operation() const
255 {
256 return d->operation;
257 }
258
setOperation(Operation operation)259 void QHttpNetworkRequest::setOperation(Operation operation)
260 {
261 d->operation = operation;
262 }
263
customVerb() const264 QByteArray QHttpNetworkRequest::customVerb() const
265 {
266 return d->customVerb;
267 }
268
setCustomVerb(const QByteArray & customVerb)269 void QHttpNetworkRequest::setCustomVerb(const QByteArray &customVerb)
270 {
271 d->customVerb = customVerb;
272 }
273
priority() const274 QHttpNetworkRequest::Priority QHttpNetworkRequest::priority() const
275 {
276 return d->priority;
277 }
278
setPriority(Priority priority)279 void QHttpNetworkRequest::setPriority(Priority priority)
280 {
281 d->priority = priority;
282 }
283
isPipeliningAllowed() const284 bool QHttpNetworkRequest::isPipeliningAllowed() const
285 {
286 return d->pipeliningAllowed;
287 }
288
setPipeliningAllowed(bool b)289 void QHttpNetworkRequest::setPipeliningAllowed(bool b)
290 {
291 d->pipeliningAllowed = b;
292 }
293
withCredentials() const294 bool QHttpNetworkRequest::withCredentials() const
295 {
296 return d->withCredentials;
297 }
298
setWithCredentials(bool b)299 void QHttpNetworkRequest::setWithCredentials(bool b)
300 {
301 d->withCredentials = b;
302 }
303
setUploadByteDevice(QNonContiguousByteDevice * bd)304 void QHttpNetworkRequest::setUploadByteDevice(QNonContiguousByteDevice *bd)
305 {
306 d->uploadByteDevice = bd;
307 }
308
uploadByteDevice() const309 QNonContiguousByteDevice* QHttpNetworkRequest::uploadByteDevice() const
310 {
311 return d->uploadByteDevice;
312 }
313
majorVersion() const314 int QHttpNetworkRequest::majorVersion() const
315 {
316 return 1;
317 }
318
minorVersion() const319 int QHttpNetworkRequest::minorVersion() const
320 {
321 return 1;
322 }
323
324
325 QT_END_NAMESPACE
326
327 #endif
328
329