1 /****************************************************************************
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
6 ** This file is part of the QtNetwork module of the Qt Toolkit.
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
40 ****************************************************************************/
42 #include "qplatformdefs.h"
43 #include "qnetworkrequest.h"
44 #include "qnetworkcookie.h"
45 #include "qnetworkrequest_p.h"
46 #include "qsslconfiguration.h"
47 #include "QtCore/qshareddata.h"
48 #include "QtCore/qlocale.h"
49 #include "QtCore/qdatetime.h"
52 #ifndef QT_NO_DATESTRING
59 \class QNetworkRequest
64 \brief The QNetworkRequest class holds a request to be sent with QNetworkAccessManager.
66 QNetworkRequest is part of the Network Access API and is the class
67 holding the information necessary to send a request over the
68 network. It contains a URL and some ancillary information that can
69 be used to modify the request.
71 \sa QNetworkReply, QNetworkAccessManager
75 \enum QNetworkRequest::KnownHeaders
77 List of known header types that QNetworkRequest parses. Each known
78 header is also represented in raw form with its full HTTP name.
80 \value ContentDispositionHeader Corresponds to the HTTP
81 Content-Disposition header and contains a string containing the
82 disposition type (for instance, attachment) and a parameter (for
85 \value ContentTypeHeader Corresponds to the HTTP Content-Type
86 header and contains a string containing the media (MIME) type and
87 any auxiliary data (for instance, charset).
89 \value ContentLengthHeader Corresponds to the HTTP Content-Length
90 header and contains the length in bytes of the data transmitted.
92 \value LocationHeader Corresponds to the HTTP Location
93 header and contains a URL representing the actual location of the
94 data, including the destination URL in case of redirections.
96 \value LastModifiedHeader Corresponds to the HTTP Last-Modified
97 header and contains a QDateTime representing the last modification
100 \value CookieHeader Corresponds to the HTTP Cookie header
101 and contains a QList<QNetworkCookie> representing the cookies to
102 be sent back to the server.
104 \value SetCookieHeader Corresponds to the HTTP Set-Cookie
105 header and contains a QList<QNetworkCookie> representing the
106 cookies sent by the server to be stored locally.
108 \value UserAgentHeader The User-Agent header sent by HTTP clients.
110 \value ServerHeader The Server header received by HTTP clients.
112 \sa header(), setHeader(), rawHeader(), setRawHeader()
116 \enum QNetworkRequest::Attribute
119 Attribute codes for the QNetworkRequest and QNetworkReply.
121 Attributes are extra meta-data that are used to control the
122 behavior of the request and to pass further information from the
123 reply back to the application. Attributes are also extensible,
124 allowing custom implementations to pass custom values.
126 The following table explains what the default attribute codes are,
127 the QVariant types associated, the default value if said attribute
128 is missing and whether it's used in requests or replies.
130 \value HttpStatusCodeAttribute
131 Replies only, type: QVariant::Int (no default)
132 Indicates the HTTP status code received from the HTTP server
133 (like 200, 304, 404, 401, etc.). If the connection was not
134 HTTP-based, this attribute will not be present.
136 \value HttpReasonPhraseAttribute
137 Replies only, type: QVariant::ByteArray (no default)
138 Indicates the HTTP reason phrase as received from the HTTP
139 server (like "Ok", "Found", "Not Found", "Access Denied",
140 etc.) This is the human-readable representation of the status
141 code (see above). If the connection was not HTTP-based, this
142 attribute will not be present.
144 \value RedirectionTargetAttribute
145 Replies only, type: QVariant::Url (no default)
146 If present, it indicates that the server is redirecting the
147 request to a different URL. The Network Access API does not by
148 default follow redirections: it's up to the application to
149 determine if the requested redirection should be allowed,
150 according to its security policies.
151 The returned URL might be relative. Use QUrl::resolved()
152 to create an absolute URL out of it.
154 \value ConnectionEncryptedAttribute
155 Replies only, type: QVariant::Bool (default: false)
156 Indicates whether the data was obtained through an encrypted
159 \value CacheLoadControlAttribute
160 Requests only, type: QVariant::Int (default: QNetworkRequest::PreferNetwork)
161 Controls how the cache should be accessed. The possible values
162 are those of QNetworkRequest::CacheLoadControl. Note that the
163 default QNetworkAccessManager implementation does not support
164 caching. However, this attribute may be used by certain
165 backends to modify their requests (for example, for caching proxies).
167 \value CacheSaveControlAttribute
168 Requests only, type: QVariant::Bool (default: true)
169 Controls if the data obtained should be saved to cache for
170 future uses. If the value is false, the data obtained will not
171 be automatically cached. If true, data may be cached, provided
172 it is cacheable (what is cacheable depends on the protocol
175 \value SourceIsFromCacheAttribute
176 Replies only, type: QVariant::Bool (default: false)
177 Indicates whether the data was obtained from cache
180 \value DoNotBufferUploadDataAttribute
181 Requests only, type: QVariant::Bool (default: false)
182 Indicates whether the QNetworkAccessManager code is
183 allowed to buffer the upload data, e.g. when doing a HTTP POST.
184 When using this flag with sequential upload data, the ContentLengthHeader
187 \value HttpPipeliningAllowedAttribute
188 Requests only, type: QVariant::Bool (default: false)
189 Indicates whether the QNetworkAccessManager code is
190 allowed to use HTTP pipelining with this request.
192 \value HttpPipeliningWasUsedAttribute
193 Replies only, type: QVariant::Bool
194 Indicates whether the HTTP pipelining was used for receiving
197 \value CustomVerbAttribute
198 Requests only, type: QVariant::ByteArray
199 Holds the value for the custom HTTP verb to send (destined for usage
200 of other verbs than GET, POST, PUT and DELETE). This verb is set
201 when calling QNetworkAccessManager::sendCustomRequest().
203 \value CookieLoadControlAttribute
204 Requests only, type: QVariant::Int (default: QNetworkRequest::Automatic)
205 Indicates whether to send 'Cookie' headers in the request.
206 This attribute is set to false by QtWebKit when creating a cross-origin
207 XMLHttpRequest where withCredentials has not been set explicitly to true by the
208 Javascript that created the request.
209 See \l{http://www.w3.org/TR/XMLHttpRequest2/#credentials-flag}{here} for more information.
210 (This value was introduced in 4.7.)
212 \value CookieSaveControlAttribute
213 Requests only, type: QVariant::Int (default: QNetworkRequest::Automatic)
214 Indicates whether to save 'Cookie' headers received from the server in reply
216 This attribute is set to false by QtWebKit when creating a cross-origin
217 XMLHttpRequest where withCredentials has not been set explicitly to true by the
218 Javascript that created the request.
219 See \l{http://www.w3.org/TR/XMLHttpRequest2/#credentials-flag} {here} for more information.
220 (This value was introduced in 4.7.)
222 \value AuthenticationReuseAttribute
223 Requests only, type: QVariant::Int (default: QNetworkRequest::Automatic)
224 Indicates whether to use cached authorization credentials in the request,
225 if available. If this is set to QNetworkRequest::Manual and the authentication
226 mechanism is 'Basic' or 'Digest', Qt will not send an an 'Authorization' HTTP
227 header with any cached credentials it may have for the request's URL.
228 This attribute is set to QNetworkRequest::Manual by QtWebKit when creating a cross-origin
229 XMLHttpRequest where withCredentials has not been set explicitly to true by the
230 Javascript that created the request.
231 See \l{http://www.w3.org/TR/XMLHttpRequest2/#credentials-flag} {here} for more information.
232 (This value was introduced in 4.7.)
234 \omitvalue MaximumDownloadBufferSizeAttribute
236 \omitvalue DownloadBufferAttribute
238 \omitvalue SynchronousRequestAttribute
240 \value BackgroundRequestAttribute
241 Type: QVariant::Bool (default: false)
242 Indicates that this is a background transfer, rather than a user initiated
243 transfer. Depending on the platform, background transfers may be subject
244 to different policies.
245 The QNetworkSession ConnectInBackground property will be set according to
249 Special type. Additional information can be passed in
250 QVariants with types ranging from User to UserMax. The default
251 implementation of Network Access will ignore any request
252 attributes in this range and it will not produce any
253 attributes in this range in replies. The range is reserved for
254 extensions of QNetworkAccessManager.
257 Special type. See User.
261 \enum QNetworkRequest::CacheLoadControl
263 Controls the caching mechanism of QNetworkAccessManager.
265 \value AlwaysNetwork always load from network and do not
266 check if the cache has a valid entry (similar to the
267 "Reload" feature in browsers); in addition, force intermediate
268 caches to re-validate.
270 \value PreferNetwork default value; load from the network
271 if the cached entry is older than the network entry. This will never
272 return stale data from the cache, but revalidate resources that
275 \value PreferCache load from cache if available,
276 otherwise load from network. Note that this can return possibly
277 stale (but not expired) items from cache.
279 \value AlwaysCache only load from cache, indicating error
280 if the item was not cached (i.e., off-line mode)
284 \enum QNetworkRequest::LoadControl
287 Indicates if an aspect of the request's loading mechanism has been
288 manually overridden, e.g. by QtWebKit.
290 \value Automatic default value: indicates default behaviour.
292 \value Manual indicates behaviour has been manually overridden.
295 class QNetworkRequestPrivate: public QSharedData, public QNetworkHeadersPrivate
298 inline QNetworkRequestPrivate()
299 : priority(QNetworkRequest::NormalPriority)
301 , sslConfiguration(0)
303 { qRegisterMetaType<QNetworkRequest>(); }
304 ~QNetworkRequestPrivate()
307 delete sslConfiguration;
312 QNetworkRequestPrivate(const QNetworkRequestPrivate &other)
313 : QSharedData(other), QNetworkHeadersPrivate(other)
316 priority = other.priority;
319 sslConfiguration = 0;
320 if (other.sslConfiguration)
321 sslConfiguration = new QSslConfiguration(*other.sslConfiguration);
325 inline bool operator==(const QNetworkRequestPrivate &other) const
327 return url == other.url &&
328 priority == other.priority &&
329 rawHeaders == other.rawHeaders &&
330 attributes == other.attributes;
331 // don't compare cookedHeaders
335 QNetworkRequest::Priority priority;
337 mutable QSslConfiguration *sslConfiguration;
342 Constructs a QNetworkRequest object with \a url as the URL to be
347 QNetworkRequest::QNetworkRequest(const QUrl &url)
348 : d(new QNetworkRequestPrivate)
354 Creates a copy of \a other.
356 QNetworkRequest::QNetworkRequest(const QNetworkRequest &other)
362 Disposes of the QNetworkRequest object.
364 QNetworkRequest::~QNetworkRequest()
366 // QSharedDataPointer auto deletes
371 Returns true if this object is the same as \a other (i.e., if they
372 have the same URL, same headers and same meta-data settings).
376 bool QNetworkRequest::operator==(const QNetworkRequest &other) const
378 return d == other.d || *d == *other.d;
382 \fn bool QNetworkRequest::operator!=(const QNetworkRequest &other) const
384 Returns false if this object is not the same as \a other.
390 Creates a copy of \a other
392 QNetworkRequest &QNetworkRequest::operator=(const QNetworkRequest &other)
399 Returns the URL this network request is referring to.
403 QUrl QNetworkRequest::url() const
409 Sets the URL this network request is referring to to be \a url.
413 void QNetworkRequest::setUrl(const QUrl &url)
419 Returns the value of the known network header \a header if it is
420 present in this request. If it is not present, returns QVariant()
421 (i.e., an invalid variant).
423 \sa KnownHeaders, rawHeader(), setHeader()
425 QVariant QNetworkRequest::header(KnownHeaders header) const
427 return d->cookedHeaders.value(header);
431 Sets the value of the known header \a header to be \a value,
432 overriding any previously set headers. This operation also sets
433 the equivalent raw HTTP header.
435 \sa KnownHeaders, setRawHeader(), header()
437 void QNetworkRequest::setHeader(KnownHeaders header, const QVariant &value)
439 d->setCookedHeader(header, value);
443 Returns true if the raw header \a headerName is present in this
446 \sa rawHeader(), setRawHeader()
448 bool QNetworkRequest::hasRawHeader(const QByteArray &headerName) const
450 return d->findRawHeader(headerName) != d->rawHeaders.constEnd();
454 Returns the raw form of header \a headerName. If no such header is
455 present, an empty QByteArray is returned, which may be
456 indistinguishable from a header that is present but has no content
457 (use hasRawHeader() to find out if the header exists or not).
459 Raw headers can be set with setRawHeader() or with setHeader().
461 \sa header(), setRawHeader()
463 QByteArray QNetworkRequest::rawHeader(const QByteArray &headerName) const
465 QNetworkHeadersPrivate::RawHeadersList::ConstIterator it =
466 d->findRawHeader(headerName);
467 if (it != d->rawHeaders.constEnd())
473 Returns a list of all raw headers that are set in this network
474 request. The list is in the order that the headers were set.
476 \sa hasRawHeader(), rawHeader()
478 QList<QByteArray> QNetworkRequest::rawHeaderList() const
480 return d->rawHeadersKeys();
484 Sets the header \a headerName to be of value \a headerValue. If \a
485 headerName corresponds to a known header (see
486 QNetworkRequest::KnownHeaders), the raw format will be parsed and
487 the corresponding "cooked" header will be set as well.
490 \snippet code/src_network_access_qnetworkrequest.cpp 0
492 will also set the known header LastModifiedHeader to be the
493 QDateTime object of the parsed date.
495 Note: setting the same header twice overrides the previous
496 setting. To accomplish the behaviour of multiple HTTP headers of
497 the same name, you should concatenate the two values, separating
498 them with a comma (",") and set one single raw header.
500 \sa KnownHeaders, setHeader(), hasRawHeader(), rawHeader()
502 void QNetworkRequest::setRawHeader(const QByteArray &headerName, const QByteArray &headerValue)
504 d->setRawHeader(headerName, headerValue);
508 Returns the attribute associated with the code \a code. If the
509 attribute has not been set, it returns \a defaultValue.
511 Note: this function does not apply the defaults listed in
512 QNetworkRequest::Attribute.
514 \sa setAttribute(), QNetworkRequest::Attribute
516 QVariant QNetworkRequest::attribute(Attribute code, const QVariant &defaultValue) const
518 return d->attributes.value(code, defaultValue);
522 Sets the attribute associated with code \a code to be value \a
523 value. If the attribute is already set, the previous value is
524 discarded. In special, if \a value is an invalid QVariant, the
527 \sa attribute(), QNetworkRequest::Attribute
529 void QNetworkRequest::setAttribute(Attribute code, const QVariant &value)
532 d->attributes.insert(code, value);
534 d->attributes.remove(code);
539 Returns this network request's SSL configuration. By default, no
540 SSL settings are specified.
542 \sa setSslConfiguration()
544 QSslConfiguration QNetworkRequest::sslConfiguration() const
546 if (!d->sslConfiguration)
547 d->sslConfiguration = new QSslConfiguration(QSslConfiguration::defaultConfiguration());
548 return *d->sslConfiguration;
552 Sets this network request's SSL configuration to be \a config. The
553 settings that apply are the private key, the local certificate,
554 the SSL protocol (SSLv2, SSLv3, TLSv1.0 where applicable), the CA
555 certificates and the ciphers that the SSL backend is allowed to
558 By default, no SSL configuration is set, which allows the backends
559 to choose freely what configuration is best for them.
561 \sa sslConfiguration(), QSslConfiguration::defaultConfiguration()
563 void QNetworkRequest::setSslConfiguration(const QSslConfiguration &config)
565 if (!d->sslConfiguration)
566 d->sslConfiguration = new QSslConfiguration(config);
568 *d->sslConfiguration = config;
575 Allows setting a reference to the \a object initiating
578 For example QtWebKit sets the originating object to the
579 QWebFrame that initiated the request.
581 \sa originatingObject()
583 void QNetworkRequest::setOriginatingObject(QObject *object)
585 d->originatingObject = object;
591 Returns a reference to the object that initiated this
592 network request; returns 0 if not set or the object has
595 \sa setOriginatingObject()
597 QObject *QNetworkRequest::originatingObject() const
599 return d->originatingObject.data();
605 Return the priority of this request.
609 QNetworkRequest::Priority QNetworkRequest::priority() const
614 /*! \enum QNetworkRequest::Priority
618 This enum lists the possible network request priorities.
620 \value HighPriority High priority
621 \value NormalPriority Normal priority
622 \value LowPriority Low priority
628 Set the priority of this request to \a priority.
630 \note The \a priority is only a hint to the network access
631 manager. It can use it or not. Currently it is used for HTTP to
632 decide which request should be sent first to a server.
636 void QNetworkRequest::setPriority(Priority priority)
638 d->priority = priority;
641 static QByteArray headerName(QNetworkRequest::KnownHeaders header)
644 case QNetworkRequest::ContentTypeHeader:
645 return "Content-Type";
647 case QNetworkRequest::ContentLengthHeader:
648 return "Content-Length";
650 case QNetworkRequest::LocationHeader:
653 case QNetworkRequest::LastModifiedHeader:
654 return "Last-Modified";
656 case QNetworkRequest::CookieHeader:
659 case QNetworkRequest::SetCookieHeader:
662 case QNetworkRequest::ContentDispositionHeader:
663 return "Content-Disposition";
665 case QNetworkRequest::UserAgentHeader:
668 case QNetworkRequest::ServerHeader:
672 // if new values are added, this will generate a compiler warning
678 static QByteArray headerValue(QNetworkRequest::KnownHeaders header, const QVariant &value)
681 case QNetworkRequest::ContentTypeHeader:
682 case QNetworkRequest::ContentLengthHeader:
683 case QNetworkRequest::ContentDispositionHeader:
684 case QNetworkRequest::UserAgentHeader:
685 case QNetworkRequest::ServerHeader:
686 return value.toByteArray();
688 case QNetworkRequest::LocationHeader:
689 switch (value.type()) {
691 return value.toUrl().toEncoded();
694 return value.toByteArray();
697 case QNetworkRequest::LastModifiedHeader:
698 switch (value.type()) {
700 case QVariant::DateTime:
701 // generate RFC 1123/822 dates:
702 return QNetworkHeadersPrivate::toHttpDate(value.toDateTime());
705 return value.toByteArray();
708 case QNetworkRequest::CookieHeader: {
709 QList<QNetworkCookie> cookies = qvariant_cast<QList<QNetworkCookie> >(value);
710 if (cookies.isEmpty() && value.userType() == qMetaTypeId<QNetworkCookie>())
711 cookies << qvariant_cast<QNetworkCookie>(value);
715 foreach (const QNetworkCookie &cookie, cookies) {
719 result += cookie.toRawForm(QNetworkCookie::NameAndValueOnly);
724 case QNetworkRequest::SetCookieHeader: {
725 QList<QNetworkCookie> cookies = qvariant_cast<QList<QNetworkCookie> >(value);
726 if (cookies.isEmpty() && value.userType() == qMetaTypeId<QNetworkCookie>())
727 cookies << qvariant_cast<QNetworkCookie>(value);
731 foreach (const QNetworkCookie &cookie, cookies) {
735 result += cookie.toRawForm(QNetworkCookie::Full);
744 static QNetworkRequest::KnownHeaders parseHeaderName(const QByteArray &headerName)
746 // headerName is not empty here
748 switch (tolower(headerName.at(0))) {
750 if (qstricmp(headerName.constData(), "content-type") == 0)
751 return QNetworkRequest::ContentTypeHeader;
752 else if (qstricmp(headerName.constData(), "content-length") == 0)
753 return QNetworkRequest::ContentLengthHeader;
754 else if (qstricmp(headerName.constData(), "cookie") == 0)
755 return QNetworkRequest::CookieHeader;
759 if (qstricmp(headerName.constData(), "location") == 0)
760 return QNetworkRequest::LocationHeader;
761 else if (qstricmp(headerName.constData(), "last-modified") == 0)
762 return QNetworkRequest::LastModifiedHeader;
766 if (qstricmp(headerName.constData(), "set-cookie") == 0)
767 return QNetworkRequest::SetCookieHeader;
768 else if (qstricmp(headerName.constData(), "server") == 0)
769 return QNetworkRequest::ServerHeader;
773 if (qstricmp(headerName.constData(), "user-agent") == 0)
774 return QNetworkRequest::UserAgentHeader;
778 return QNetworkRequest::KnownHeaders(-1); // nothing found
781 static QVariant parseHttpDate(const QByteArray &raw)
783 QDateTime dt = QNetworkHeadersPrivate::fromHttpDate(raw);
786 return QVariant(); // transform an invalid QDateTime into a null QVariant
789 static QVariant parseCookieHeader(const QByteArray &raw)
791 QList<QNetworkCookie> result;
792 QList<QByteArray> cookieList = raw.split(';');
793 foreach (const QByteArray &cookie, cookieList) {
794 QList<QNetworkCookie> parsed = QNetworkCookie::parseCookies(cookie.trimmed());
795 if (parsed.count() != 1)
796 return QVariant(); // invalid Cookie: header
801 return QVariant::fromValue(result);
804 static QVariant parseHeaderValue(QNetworkRequest::KnownHeaders header, const QByteArray &value)
806 // header is always a valid value
808 case QNetworkRequest::UserAgentHeader:
809 case QNetworkRequest::ServerHeader:
810 case QNetworkRequest::ContentTypeHeader:
811 // copy exactly, convert to QString
812 return QString::fromLatin1(value);
814 case QNetworkRequest::ContentLengthHeader: {
816 qint64 result = value.trimmed().toLongLong(&ok);
822 case QNetworkRequest::LocationHeader: {
823 QUrl result = QUrl::fromEncoded(value, QUrl::StrictMode);
824 if (result.isValid() && !result.scheme().isEmpty())
829 case QNetworkRequest::LastModifiedHeader:
830 return parseHttpDate(value);
832 case QNetworkRequest::CookieHeader:
833 return parseCookieHeader(value);
835 case QNetworkRequest::SetCookieHeader:
836 return QVariant::fromValue(QNetworkCookie::parseCookies(value));
844 QNetworkHeadersPrivate::RawHeadersList::ConstIterator
845 QNetworkHeadersPrivate::findRawHeader(const QByteArray &key) const
847 RawHeadersList::ConstIterator it = rawHeaders.constBegin();
848 RawHeadersList::ConstIterator end = rawHeaders.constEnd();
849 for ( ; it != end; ++it)
850 if (qstricmp(it->first.constData(), key.constData()) == 0)
853 return end; // not found
856 QNetworkHeadersPrivate::RawHeadersList QNetworkHeadersPrivate::allRawHeaders() const
861 QList<QByteArray> QNetworkHeadersPrivate::rawHeadersKeys() const
863 QList<QByteArray> result;
864 RawHeadersList::ConstIterator it = rawHeaders.constBegin(),
865 end = rawHeaders.constEnd();
866 for ( ; it != end; ++it)
872 void QNetworkHeadersPrivate::setRawHeader(const QByteArray &key, const QByteArray &value)
875 // refuse to accept an empty raw header
878 setRawHeaderInternal(key, value);
879 parseAndSetHeader(key, value);
884 Sets the internal raw headers list to match \a list. The cooked headers
885 will also be updated.
887 If \a list contains duplicates, they will be stored, but only the first one
890 void QNetworkHeadersPrivate::setAllRawHeaders(const RawHeadersList &list)
892 cookedHeaders.clear();
895 RawHeadersList::ConstIterator it = rawHeaders.constBegin();
896 RawHeadersList::ConstIterator end = rawHeaders.constEnd();
897 for ( ; it != end; ++it)
898 parseAndSetHeader(it->first, it->second);
901 void QNetworkHeadersPrivate::setCookedHeader(QNetworkRequest::KnownHeaders header,
902 const QVariant &value)
904 QByteArray name = headerName(header);
905 if (name.isEmpty()) {
906 // headerName verifies that \a header is a known value
907 qWarning("QNetworkRequest::setHeader: invalid header value KnownHeader(%d) received", header);
911 if (value.isNull()) {
912 setRawHeaderInternal(name, QByteArray());
913 cookedHeaders.remove(header);
915 QByteArray rawValue = headerValue(header, value);
916 if (rawValue.isEmpty()) {
917 qWarning("QNetworkRequest::setHeader: QVariant of type %s cannot be used with header %s",
918 value.typeName(), name.constData());
922 setRawHeaderInternal(name, rawValue);
923 cookedHeaders.insert(header, value);
927 void QNetworkHeadersPrivate::setRawHeaderInternal(const QByteArray &key, const QByteArray &value)
929 RawHeadersList::Iterator it = rawHeaders.begin();
930 while (it != rawHeaders.end()) {
931 if (qstricmp(it->first.constData(), key.constData()) == 0)
932 it = rawHeaders.erase(it);
938 return; // only wanted to erase key
943 rawHeaders.append(pair);
946 void QNetworkHeadersPrivate::parseAndSetHeader(const QByteArray &key, const QByteArray &value)
948 // is it a known header?
949 QNetworkRequest::KnownHeaders parsedKey = parseHeaderName(key);
950 if (parsedKey != QNetworkRequest::KnownHeaders(-1)) {
951 if (value.isNull()) {
952 cookedHeaders.remove(parsedKey);
953 } else if (parsedKey == QNetworkRequest::ContentLengthHeader
954 && cookedHeaders.contains(QNetworkRequest::ContentLengthHeader)) {
955 // Only set the cooked header "Content-Length" once.
956 // See bug QTBUG-15311
958 cookedHeaders.insert(parsedKey, parseHeaderValue(parsedKey, value));
964 // Fast month string to int conversion. This code
965 // assumes that the Month name is correct and that
966 // the string is at least three chars long.
967 static int name_to_month(const char* month_str)
969 switch (month_str[0]) {
971 switch (month_str[1]) {
976 switch (month_str[2] ) {
990 switch (month_str[2] ) {
1000 switch (month_str[1]) {
1026 QDateTime QNetworkHeadersPrivate::fromHttpDate(const QByteArray &value)
1028 // HTTP dates have three possible formats:
1029 // RFC 1123/822 - ddd, dd MMM yyyy hh:mm:ss "GMT"
1030 // RFC 850 - dddd, dd-MMM-yy hh:mm:ss "GMT"
1031 // ANSI C's asctime - ddd MMM d hh:mm:ss yyyy
1032 // We only handle them exactly. If they deviate, we bail out.
1034 int pos = value.indexOf(',');
1036 #ifndef QT_NO_DATESTRING
1038 // no comma -> asctime(3) format
1039 dt = QDateTime::fromString(QString::fromLatin1(value), Qt::TextDate);
1041 // Use sscanf over QLocal/QDateTimeParser for speed reasons. See the
1042 // QtWebKit performance benchmarks to get an idea.
1045 int day, year, hour, minute, second;
1046 if (sscanf(value.constData(), "%*3s, %d %3s %d %d:%d:%d 'GMT'", &day, month_name, &year, &hour, &minute, &second) == 6)
1047 dt = QDateTime(QDate(year, name_to_month(month_name), day), QTime(hour, minute, second));
1049 QLocale c = QLocale::c();
1050 // eat the weekday, the comma and the space following it
1051 QString sansWeekday = QString::fromLatin1(value.constData() + pos + 2);
1052 // must be RFC 850 date
1053 dt = c.toDateTime(sansWeekday, QLatin1String("dd-MMM-yy hh:mm:ss 'GMT'"));
1056 #endif // QT_NO_DATESTRING
1059 dt.setTimeSpec(Qt::UTC);
1063 QByteArray QNetworkHeadersPrivate::toHttpDate(const QDateTime &dt)
1065 return QLocale::c().toString(dt, QLatin1String("ddd, dd MMM yyyy hh:mm:ss 'GMT'"))