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 "qnetworkaccessmanager.h"
43 #include "qnetworkaccessmanager_p.h"
44 #include "qnetworkrequest.h"
45 #include "qnetworkreply.h"
46 #include "qnetworkreply_p.h"
47 #include "qnetworkcookie.h"
48 #include "qnetworkcookiejar.h"
49 #include "qabstractnetworkcache.h"
51 #include "QtNetwork/qnetworksession.h"
52 #include "QtNetwork/private/qsharednetworksession_p.h"
54 #include "qnetworkaccessftpbackend_p.h"
55 #include "qnetworkaccessfilebackend_p.h"
56 #include "qnetworkaccessdebugpipebackend_p.h"
57 #include "qnetworkaccesscachebackend_p.h"
58 #include "qnetworkreplydataimpl_p.h"
59 #include "qnetworkreplyfileimpl_p.h"
61 #include "QtCore/qbuffer.h"
62 #include "QtCore/qurl.h"
63 #include "QtCore/qvector.h"
64 #include "QtNetwork/private/qauthenticator_p.h"
65 #include "QtNetwork/qsslconfiguration.h"
66 #include "QtNetwork/qnetworkconfigmanager.h"
67 #include "QtNetwork/qhttpmultipart.h"
68 #include "qhttpmultipart_p.h"
70 #include "qnetworkreplyhttpimpl_p.h"
76 Q_GLOBAL_STATIC(QNetworkAccessFileBackendFactory, fileBackend)
78 Q_GLOBAL_STATIC(QNetworkAccessFtpBackendFactory, ftpBackend)
81 #ifdef QT_BUILD_INTERNAL
82 Q_GLOBAL_STATIC(QNetworkAccessDebugPipeBackendFactory, debugpipeBackend)
85 #if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
87 #include <CoreServices/CoreServices.h>
88 #include <SystemConfiguration/SystemConfiguration.h>
89 #include <Security/SecKeychain.h>
91 bool getProxyAuth(const QString& proxyHostname, const QString &scheme, QString& username, QString& password)
94 SecKeychainItemRef itemRef;
95 bool retValue = false;
96 SecProtocolType protocolType = kSecProtocolTypeAny;
97 if (scheme.compare(QLatin1String("ftp"),Qt::CaseInsensitive)==0) {
98 protocolType = kSecProtocolTypeFTP;
99 } else if (scheme.compare(QLatin1String("http"),Qt::CaseInsensitive)==0) {
100 protocolType = kSecProtocolTypeHTTP;
101 } else if (scheme.compare(QLatin1String("https"),Qt::CaseInsensitive)==0) {
102 protocolType = kSecProtocolTypeHTTPS;
104 QByteArray proxyHostnameUtf8(proxyHostname.toUtf8());
105 err = SecKeychainFindInternetPassword(NULL,
106 proxyHostnameUtf8.length(), proxyHostnameUtf8.constData(),
112 kSecAuthenticationTypeAny,
117 SecKeychainAttribute attr;
118 SecKeychainAttributeList attrList;
122 attr.tag = kSecAccountItemAttr;
127 attrList.attr = &attr;
129 if (SecKeychainItemCopyContent(itemRef, NULL, &attrList, &length, &outData) == noErr) {
130 username = QString::fromUtf8((const char*)attr.data, attr.length);
131 password = QString::fromUtf8((const char*)outData, length);
132 SecKeychainItemFreeContent(&attrList,outData);
143 static void ensureInitialized()
149 #ifdef QT_BUILD_INTERNAL
150 (void) debugpipeBackend();
153 // leave this one last since it will query the special QAbstractFileEngines
154 (void) fileBackend();
158 \class QNetworkAccessManager
159 \brief The QNetworkAccessManager class allows the application to
160 send network requests and receive replies
167 The Network Access API is constructed around one QNetworkAccessManager
168 object, which holds the common configuration and settings for the requests
169 it sends. It contains the proxy and cache configuration, as well as the
170 signals related to such issues, and reply signals that can be used to
171 monitor the progress of a network operation. One QNetworkAccessManager
172 should be enough for the whole Qt application.
174 Once a QNetworkAccessManager object has been created, the application can
175 use it to send requests over the network. A group of standard functions
176 are supplied that take a request and optional data, and each return a
177 QNetworkReply object. The returned object is used to obtain any data
178 returned in response to the corresponding request.
180 A simple download off the network could be accomplished with:
181 \snippet code/src_network_access_qnetworkaccessmanager.cpp 0
183 QNetworkAccessManager has an asynchronous API.
184 When the \tt replyFinished slot above is called, the parameter it
185 takes is the QNetworkReply object containing the downloaded data
186 as well as meta-data (headers, etc.).
188 \note After the request has finished, it is the responsibility of the user
189 to delete the QNetworkReply object at an appropriate time. Do not directly
190 delete it inside the slot connected to finished(). You can use the
191 deleteLater() function.
193 \note QNetworkAccessManager queues the requests it receives. The number
194 of requests executed in parallel is dependent on the protocol.
195 Currently, for the HTTP protocol on desktop platforms, 6 requests are
196 executed in parallel for one host/port combination.
198 A more involved example, assuming the manager is already existent,
200 \snippet code/src_network_access_qnetworkaccessmanager.cpp 1
202 \section1 Network and Roaming support
204 With the addition of the \l {Bearer Management} API to Qt 4.7
205 QNetworkAccessManager gained the ability to manage network connections.
206 QNetworkAccessManager can start the network interface if the device is
207 offline and terminates the interface if the current process is the last
208 one to use the uplink. Note that some platform utilize grace periods from
209 when the last application stops using a uplink until the system actually
210 terminates the connectivity link. Roaming is equally transparent. Any
211 queued/pending network requests are automatically transferred to new
214 Clients wanting to utilize this feature should not require any changes. In fact
215 it is likely that existing platform specific connection code can simply be
216 removed from the application.
218 \note The network and roaming support in QNetworkAccessManager is conditional
219 upon the platform supporting connection management. The
220 \l QNetworkConfigurationManager::NetworkSessionRequired can be used to
221 detect whether QNetworkAccessManager utilizes this feature. Currently only
222 Meego/Harmattan platforms provide connection management support.
224 \note This feature cannot be used in combination with the Bearer Management
225 API as provided by QtMobility. Applications have to migrate to the Qt version
226 of Bearer Management.
228 \sa QNetworkRequest, QNetworkReply, QNetworkProxy
232 \enum QNetworkAccessManager::Operation
234 Indicates the operation this reply is processing.
236 \value HeadOperation retrieve headers operation (created
239 \value GetOperation retrieve headers and download contents
242 \value PutOperation upload contents operation (created
245 \value PostOperation send the contents of an HTML form for
246 processing via HTTP POST (created with post())
248 \value DeleteOperation delete contents operation (created with
251 \value CustomOperation custom operation (created with
252 sendCustomRequest()) \since 4.7
254 \omitvalue UnknownOperation
256 \sa QNetworkReply::operation()
260 \enum QNetworkAccessManager::NetworkAccessibility
262 Indicates whether the network is accessible via this network access manager.
264 \value UnknownAccessibility The network accessibility cannot be determined.
265 \value NotAccessible The network is not currently accessible, either because there
266 is currently no network coverage or network access has been
267 explicitly disabled by a call to setNetworkAccessible().
268 \value Accessible The network is accessible.
270 \sa networkAccessible
274 \property QNetworkAccessManager::networkAccessible
275 \brief whether the network is currently accessible via this network access manager.
279 If the network is \l {NotAccessible}{not accessible} the network access manager will not
280 process any new network requests, all such requests will fail with an error. Requests with
281 URLs with the file:// scheme will still be processed.
283 By default the value of this property reflects the physical state of the device. Applications
284 may override it to disable all network requests via this network access manager by calling
286 \snippet code/src_network_access_qnetworkaccessmanager.cpp 4
288 Network requests can be reenabled again by calling
290 \snippet code/src_network_access_qnetworkaccessmanager.cpp 5
292 \note Calling setNetworkAccessible() does not change the network state.
296 \fn void QNetworkAccessManager::networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible)
298 This signal is emitted when the value of the \l networkAccessible property changes.
299 \a accessible is the new network accessibility.
303 \fn void QNetworkAccessManager::networkSessionConnected()
309 This signal is emitted when the status of the network session changes into a usable (Connected)
310 state. It is used to signal to QNetworkReplys to start or migrate their network operation once
311 the network session has been opened or finished roaming.
315 \fn void QNetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
317 This signal is emitted whenever a proxy requests authentication
318 and QNetworkAccessManager cannot find a valid, cached
319 credential. The slot connected to this signal should fill in the
320 credentials for the proxy \a proxy in the \a authenticator object.
322 QNetworkAccessManager will cache the credentials internally. The
323 next time the proxy requests authentication, QNetworkAccessManager
324 will automatically send the same credential without emitting the
325 proxyAuthenticationRequired signal again.
327 If the proxy rejects the credentials, QNetworkAccessManager will
328 emit the signal again.
330 \sa proxy(), setProxy(), authenticationRequired()
334 \fn void QNetworkAccessManager::authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator)
336 This signal is emitted whenever a final server requests
337 authentication before it delivers the requested contents. The slot
338 connected to this signal should fill the credentials for the
339 contents (which can be determined by inspecting the \a reply
340 object) in the \a authenticator object.
342 QNetworkAccessManager will cache the credentials internally and
343 will send the same values if the server requires authentication
344 again, without emitting the authenticationRequired() signal. If it
345 rejects the credentials, this signal will be emitted again.
347 \note To have the request not send credentials you must not call
348 setUser() or setPassword() on the \a authenticator object. This
349 will result in the the \l finished() signal being emitted with a
350 \l QNetworkReply with error \l AuthenticationRequiredError.
352 \note It is not possible to use a QueuedConnection to connect to
353 this signal, as the connection will fail if the authenticator has
354 not been filled in with new information when the signal returns.
356 \sa proxyAuthenticationRequired(), QAuthenticator::setUser(), QAuthenticator::setPassword()
360 \fn void QNetworkAccessManager::finished(QNetworkReply *reply)
362 This signal is emitted whenever a pending network reply is
363 finished. The \a reply parameter will contain a pointer to the
364 reply that has just finished. This signal is emitted in tandem
365 with the QNetworkReply::finished() signal.
367 See QNetworkReply::finished() for information on the status that
368 the object will be in.
370 \note Do not delete the \a reply object in the slot connected to this
371 signal. Use deleteLater().
373 \sa QNetworkReply::finished(), QNetworkReply::error()
377 \fn void QNetworkAccessManager::sslErrors(QNetworkReply *reply, const QList<QSslError> &errors)
379 This signal is emitted if the SSL/TLS session encountered errors
380 during the set up, including certificate verification errors. The
381 \a errors parameter contains the list of errors and \a reply is
382 the QNetworkReply that is encountering these errors.
384 To indicate that the errors are not fatal and that the connection
385 should proceed, the QNetworkReply::ignoreSslErrors() function should be called
386 from the slot connected to this signal. If it is not called, the
387 SSL session will be torn down before any data is exchanged
390 This signal can be used to display an error message to the user
391 indicating that security may be compromised and display the
392 SSL settings (see sslConfiguration() to obtain it). If the user
393 decides to proceed after analyzing the remote certificate, the
394 slot should call ignoreSslErrors().
396 \sa QSslSocket::sslErrors(), QNetworkReply::sslErrors(),
397 QNetworkReply::sslConfiguration(), QNetworkReply::ignoreSslErrors()
402 Constructs a QNetworkAccessManager object that is the center of
403 the Network Access API and sets \a parent as the parent object.
405 QNetworkAccessManager::QNetworkAccessManager(QObject *parent)
406 : QObject(*new QNetworkAccessManagerPrivate, parent)
410 qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
411 #ifndef QT_NO_NETWORKPROXY
412 qRegisterMetaType<QNetworkProxy>("QNetworkProxy");
415 qRegisterMetaType<QList<QSslError> >("QList<QSslError>");
416 qRegisterMetaType<QSslConfiguration>("QSslConfiguration");
418 qRegisterMetaType<QList<QPair<QByteArray,QByteArray> > >("QList<QPair<QByteArray,QByteArray> >");
419 qRegisterMetaType<QHttpNetworkRequest>("QHttpNetworkRequest");
420 qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
421 qRegisterMetaType<QSharedPointer<char> >("QSharedPointer<char>");
425 Destroys the QNetworkAccessManager object and frees up any
426 resources. Note that QNetworkReply objects that are returned from
427 this class have this object set as their parents, which means that
428 they will be deleted along with it if you don't call
429 QObject::setParent() on them.
431 QNetworkAccessManager::~QNetworkAccessManager()
433 #ifndef QT_NO_NETWORKPROXY
434 delete d_func()->proxyFactory;
437 // Delete the QNetworkReply children first.
438 // Else a QAbstractNetworkCache might get deleted in ~QObject
439 // before a QNetworkReply that accesses the QAbstractNetworkCache
440 // object in its destructor.
441 qDeleteAll(findChildren<QNetworkReply *>());
442 // The other children will be deleted in this ~QObject
443 // FIXME instead of this "hack" make the QNetworkReplyImpl
444 // properly watch the cache deletion, e.g. via a QWeakPointer.
447 #ifndef QT_NO_NETWORKPROXY
449 Returns the QNetworkProxy that the requests sent using this
450 QNetworkAccessManager object will use. The default value for the
451 proxy is QNetworkProxy::DefaultProxy.
453 \sa setProxy(), setProxyFactory(), proxyAuthenticationRequired()
455 QNetworkProxy QNetworkAccessManager::proxy() const
457 return d_func()->proxy;
461 Sets the proxy to be used in future requests to be \a proxy. This
462 does not affect requests that have already been sent. The
463 proxyAuthenticationRequired() signal will be emitted if the proxy
464 requests authentication.
466 A proxy set with this function will be used for all requests
467 issued by QNetworkAccessManager. In some cases, it might be
468 necessary to select different proxies depending on the type of
469 request being sent or the destination host. If that's the case,
470 you should consider using setProxyFactory().
472 \sa proxy(), proxyAuthenticationRequired()
474 void QNetworkAccessManager::setProxy(const QNetworkProxy &proxy)
476 Q_D(QNetworkAccessManager);
477 delete d->proxyFactory;
483 \fn QNetworkProxyFactory *QNetworkAccessManager::proxyFactory() const
486 Returns the proxy factory that this QNetworkAccessManager object
487 is using to determine the proxies to be used for requests.
489 Note that the pointer returned by this function is managed by
490 QNetworkAccessManager and could be deleted at any time.
492 \sa setProxyFactory(), proxy()
494 QNetworkProxyFactory *QNetworkAccessManager::proxyFactory() const
496 return d_func()->proxyFactory;
502 Sets the proxy factory for this class to be \a factory. A proxy
503 factory is used to determine a more specific list of proxies to be
504 used for a given request, instead of trying to use the same proxy
505 value for all requests.
507 All queries sent by QNetworkAccessManager will have type
508 QNetworkProxyQuery::UrlRequest.
510 For example, a proxy factory could apply the following rules:
512 \li if the target address is in the local network (for example,
513 if the hostname contains no dots or if it's an IP address in
514 the organization's range), return QNetworkProxy::NoProxy
515 \li if the request is FTP, return an FTP proxy
516 \li if the request is HTTP or HTTPS, then return an HTTP proxy
517 \li otherwise, return a SOCKSv5 proxy server
520 The lifetime of the object \a factory will be managed by
521 QNetworkAccessManager. It will delete the object when necessary.
523 \note If a specific proxy is set with setProxy(), the factory will not
526 \sa proxyFactory(), setProxy(), QNetworkProxyQuery
528 void QNetworkAccessManager::setProxyFactory(QNetworkProxyFactory *factory)
530 Q_D(QNetworkAccessManager);
531 delete d->proxyFactory;
532 d->proxyFactory = factory;
533 d->proxy = QNetworkProxy();
540 Returns the cache that is used to store data obtained from the network.
544 QAbstractNetworkCache *QNetworkAccessManager::cache() const
546 Q_D(const QNetworkAccessManager);
547 return d->networkCache;
553 Sets the manager's network cache to be the \a cache specified. The cache
554 is used for all requests dispatched by the manager.
556 Use this function to set the network cache object to a class that implements
557 additional features, like saving the cookies to permanent storage.
559 \note QNetworkAccessManager takes ownership of the \a cache object.
561 QNetworkAccessManager by default does not have a set cache.
562 Qt provides a simple disk cache, QNetworkDiskCache, which can be used.
564 \sa cache(), QNetworkRequest::CacheLoadControl
566 void QNetworkAccessManager::setCache(QAbstractNetworkCache *cache)
568 Q_D(QNetworkAccessManager);
569 if (d->networkCache != cache) {
570 delete d->networkCache;
571 d->networkCache = cache;
573 d->networkCache->setParent(this);
578 Returns the QNetworkCookieJar that is used to store cookies
579 obtained from the network as well as cookies that are about to be
584 QNetworkCookieJar *QNetworkAccessManager::cookieJar() const
586 Q_D(const QNetworkAccessManager);
588 d->createCookieJar();
593 Sets the manager's cookie jar to be the \a cookieJar specified.
594 The cookie jar is used by all requests dispatched by the manager.
596 Use this function to set the cookie jar object to a class that
597 implements additional features, like saving the cookies to permanent
600 \note QNetworkAccessManager takes ownership of the \a cookieJar object.
602 If \a cookieJar is in the same thread as this QNetworkAccessManager,
603 it will set the parent of the \a cookieJar
604 so that the cookie jar is deleted when this
605 object is deleted as well. If you want to share cookie jars
606 between different QNetworkAccessManager objects, you may want to
607 set the cookie jar's parent to 0 after calling this function.
609 QNetworkAccessManager by default does not implement any cookie
610 policy of its own: it accepts all cookies sent by the server, as
611 long as they are well formed and meet the minimum security
612 requirements (cookie domain matches the request's and cookie path
613 matches the request's). In order to implement your own security
614 policy, override the QNetworkCookieJar::cookiesForUrl() and
615 QNetworkCookieJar::setCookiesFromUrl() virtual functions. Those
616 functions are called by QNetworkAccessManager when it detects a
619 \sa cookieJar(), QNetworkCookieJar::cookiesForUrl(), QNetworkCookieJar::setCookiesFromUrl()
621 void QNetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
623 Q_D(QNetworkAccessManager);
624 d->cookieJarCreated = true;
625 if (d->cookieJar != cookieJar) {
626 if (d->cookieJar && d->cookieJar->parent() == this)
628 d->cookieJar = cookieJar;
629 if (thread() == cookieJar->thread())
630 d->cookieJar->setParent(this);
635 Posts a request to obtain the network headers for \a request
636 and returns a new QNetworkReply object which will contain such headers.
638 The function is named after the HTTP request associated (HEAD).
640 QNetworkReply *QNetworkAccessManager::head(const QNetworkRequest &request)
642 return d_func()->postProcess(createRequest(QNetworkAccessManager::HeadOperation, request));
646 Posts a request to obtain the contents of the target \a request
647 and returns a new QNetworkReply object opened for reading which emits the
648 \l{QIODevice::readyRead()}{readyRead()} signal whenever new data
651 The contents as well as associated headers will be downloaded.
653 \sa post(), put(), deleteResource(), sendCustomRequest()
655 QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
657 return d_func()->postProcess(createRequest(QNetworkAccessManager::GetOperation, request));
661 Sends an HTTP POST request to the destination specified by \a request
662 and returns a new QNetworkReply object opened for reading that will
663 contain the reply sent by the server. The contents of the \a data
664 device will be uploaded to the server.
666 \a data must be open for reading and must remain valid until the
667 finished() signal is emitted for this reply.
669 \note Sending a POST request on protocols other than HTTP and
670 HTTPS is undefined and will probably fail.
672 \sa get(), put(), deleteResource(), sendCustomRequest()
674 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
676 return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation, request, data));
682 Sends the contents of the \a data byte array to the destination
683 specified by \a request.
685 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data)
687 QBuffer *buffer = new QBuffer;
688 buffer->setData(data);
689 buffer->open(QIODevice::ReadOnly);
691 QNetworkReply *reply = post(request, buffer);
692 buffer->setParent(reply);
701 Sends the contents of the \a multiPart message to the destination
702 specified by \a request.
704 This can be used for sending MIME multipart messages over HTTP.
706 \sa QHttpMultiPart, QHttpPart, put()
708 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
710 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
711 QIODevice *device = multiPart->d_func()->device;
712 QNetworkReply *reply = post(newRequest, device);
721 Sends the contents of the \a multiPart message to the destination
722 specified by \a request.
724 This can be used for sending MIME multipart messages over HTTP.
726 \sa QHttpMultiPart, QHttpPart, post()
728 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
730 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
731 QIODevice *device = multiPart->d_func()->device;
732 QNetworkReply *reply = put(newRequest, device);
737 Uploads the contents of \a data to the destination \a request and
738 returnes a new QNetworkReply object that will be open for reply.
740 \a data must be opened for reading when this function is called
741 and must remain valid until the finished() signal is emitted for
744 Whether anything will be available for reading from the returned
745 object is protocol dependent. For HTTP, the server may send a
746 small HTML page indicating the upload was successful (or not).
747 Other protocols will probably have content in their replies.
749 \note For HTTP, this request will send a PUT request, which most servers
750 do not allow. Form upload mechanisms, including that of uploading
751 files through HTML forms, use the POST mechanism.
753 \sa get(), post(), deleteResource(), sendCustomRequest()
755 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data)
757 return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, data));
763 Sends the contents of the \a data byte array to the destination
764 specified by \a request.
766 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
768 QBuffer *buffer = new QBuffer;
769 buffer->setData(data);
770 buffer->open(QIODevice::ReadOnly);
772 QNetworkReply *reply = put(request, buffer);
773 buffer->setParent(reply);
780 Sends a request to delete the resource identified by the URL of \a request.
782 \note This feature is currently available for HTTP only, performing an
785 \sa get(), post(), put(), sendCustomRequest()
787 QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &request)
789 return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
792 #ifndef QT_NO_BEARERMANAGEMENT
797 Sets the network configuration that will be used when creating the
798 \l {QNetworkSession}{network session} to \a config.
800 The network configuration is used to create and open a network session before any request that
801 requires network access is process. If no network configuration is explicitly set via this
802 function the network configuration returned by
803 QNetworkConfigurationManager::defaultConfiguration() will be used.
805 To restore the default network configuration set the network configuration to the value
806 returned from QNetworkConfigurationManager::defaultConfiguration().
808 \snippet code/src_network_access_qnetworkaccessmanager.cpp 2
810 If an invalid network configuration is set, a network session will not be created. In this
811 case network requests will be processed regardless, but may fail. For example:
813 \snippet code/src_network_access_qnetworkaccessmanager.cpp 3
815 \sa configuration(), QNetworkSession
817 void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config)
819 d_func()->createSession(config);
825 Returns the network configuration that will be used to create the
826 \l {QNetworkSession}{network session} which will be used when processing network requests.
828 \sa setConfiguration(), activeConfiguration()
830 QNetworkConfiguration QNetworkAccessManager::configuration() const
832 Q_D(const QNetworkAccessManager);
834 if (d->networkSession)
835 return d->networkSession->configuration();
837 return QNetworkConfiguration();
843 Returns the current active network configuration.
845 If the network configuration returned by configuration() is of type
846 QNetworkConfiguration::ServiceNetwork this function will return the current active child
847 network configuration of that configuration. Otherwise returns the same network configuration
850 Use this function to return the actual network configuration currently in use by the network
855 QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
857 Q_D(const QNetworkAccessManager);
859 if (d->networkSession) {
860 QNetworkConfigurationManager manager;
862 return manager.configurationFromIdentifier(
863 d->networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString());
865 return QNetworkConfiguration();
872 Overrides the reported network accessibility. If \a accessible is NotAccessible the reported
873 network accessiblity will always be NotAccessible. Otherwise the reported network
874 accessibility will reflect the actual device state.
876 void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible)
878 Q_D(QNetworkAccessManager);
880 if (d->networkAccessible != accessible) {
881 NetworkAccessibility previous = networkAccessible();
882 d->networkAccessible = accessible;
883 NetworkAccessibility current = networkAccessible();
884 if (previous != current)
885 emit networkAccessibleChanged(current);
892 Returns the current network accessibility.
894 QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const
896 Q_D(const QNetworkAccessManager);
898 if (d->networkSession) {
899 // d->online holds online/offline state of this network session.
901 return d->networkAccessible;
903 return NotAccessible;
905 // Network accessibility is either disabled or unknown.
906 return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility;
913 Returns the network session currently in use.
914 This can be changed at any time, ownership remains with the QNetworkAccessManager
916 const QWeakPointer<const QNetworkSession> QNetworkAccessManagerPrivate::getNetworkSession(const QNetworkAccessManager *q)
918 return q->d_func()->networkSession.toWeakRef();
921 #endif // QT_NO_BEARERMANAGEMENT
926 Sends a custom request to the server identified by the URL of \a request.
928 It is the user's responsibility to send a \a verb to the server that is valid
929 according to the HTTP specification.
931 This method provides means to send verbs other than the common ones provided
932 via get() or post() etc., for instance sending an HTTP OPTIONS command.
934 If \a data is not empty, the contents of the \a data
935 device will be uploaded to the server; in that case, data must be open for
936 reading and must remain valid until the finished() signal is emitted for this reply.
938 \note This feature is currently available for HTTP(S) only.
940 \sa get(), post(), put(), deleteResource()
942 QNetworkReply *QNetworkAccessManager::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
944 QNetworkRequest newRequest(request);
945 newRequest.setAttribute(QNetworkRequest::CustomVerbAttribute, verb);
946 return d_func()->postProcess(createRequest(QNetworkAccessManager::CustomOperation, newRequest, data));
950 Returns a new QNetworkReply object to handle the operation \a op
951 and request \a req. The device \a outgoingData is always 0 for Get and
952 Head requests, but is the value passed to post() and put() in
953 those operations (the QByteArray variants will pass a QBuffer
956 The default implementation calls QNetworkCookieJar::cookiesForUrl()
957 on the cookie jar set with setCookieJar() to obtain the cookies to
958 be sent to the remote server.
960 The returned object must be in an open state.
962 QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op,
963 const QNetworkRequest &req,
964 QIODevice *outgoingData)
966 Q_D(QNetworkAccessManager);
968 bool isLocalFile = req.url().isLocalFile();
969 QString scheme = req.url().scheme().toLower();
971 // fast path for GET on file:// URLs
972 // The QNetworkAccessFileBackend will right now only be used for PUT
973 if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
974 && (isLocalFile || scheme == QLatin1String("qrc"))) {
975 return new QNetworkReplyFileImpl(this, req, op);
978 if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
979 && scheme == QLatin1String("data")) {
980 return new QNetworkReplyDataImpl(this, req, op);
983 // A request with QNetworkRequest::AlwaysCache does not need any bearer management
984 QNetworkRequest::CacheLoadControl mode =
985 static_cast<QNetworkRequest::CacheLoadControl>(
986 req.attribute(QNetworkRequest::CacheLoadControlAttribute,
987 QNetworkRequest::PreferNetwork).toInt());
988 if (mode == QNetworkRequest::AlwaysCache
989 && (op == QNetworkAccessManager::GetOperation
990 || op == QNetworkAccessManager::HeadOperation)) {
991 // FIXME Implement a QNetworkReplyCacheImpl instead, see QTBUG-15106
992 QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
993 QNetworkReplyImplPrivate *priv = reply->d_func();
994 priv->manager = this;
995 priv->backend = new QNetworkAccessCacheBackend();
996 priv->backend->manager = this->d_func();
997 priv->backend->setParent(reply);
998 priv->backend->reply = priv;
999 priv->setup(op, req, outgoingData);
1003 #ifndef QT_NO_BEARERMANAGEMENT
1004 // Return a disabled network reply if network access is disabled.
1005 // Except if the scheme is empty or file://.
1006 if (!d->networkAccessible && !isLocalFile) {
1007 return new QDisabledNetworkReply(this, req, op);
1010 if (!d->networkSession && (d->initializeSession || !d->networkConfiguration.isEmpty())) {
1011 QNetworkConfigurationManager manager;
1012 if (!d->networkConfiguration.isEmpty()) {
1013 d->createSession(manager.configurationFromIdentifier(d->networkConfiguration));
1015 if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired)
1016 d->createSession(manager.defaultConfiguration());
1018 d->initializeSession = false;
1023 QNetworkRequest request = req;
1024 if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() &&
1025 outgoingData && !outgoingData->isSequential()) {
1026 // request has no Content-Length
1027 // but the data that is outgoing is random-access
1028 request.setHeader(QNetworkRequest::ContentLengthHeader, outgoingData->size());
1031 if (static_cast<QNetworkRequest::LoadControl>
1032 (request.attribute(QNetworkRequest::CookieLoadControlAttribute,
1033 QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Automatic) {
1035 QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
1036 if (!cookies.isEmpty())
1037 request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies));
1042 // Since Qt 5 we use the new QNetworkReplyHttpImpl
1043 if (scheme == QLatin1String("http")
1045 || scheme == QLatin1String("https")
1048 QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
1049 #ifndef QT_NO_BEARERMANAGEMENT
1050 connect(this, SIGNAL(networkSessionConnected()),
1051 reply, SLOT(_q_networkSessionConnected()));
1055 #endif // QT_NO_HTTP
1057 // first step: create the reply
1058 QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
1059 #ifndef QT_NO_BEARERMANAGEMENT
1061 connect(this, SIGNAL(networkSessionConnected()),
1062 reply, SLOT(_q_networkSessionConnected()));
1065 QNetworkReplyImplPrivate *priv = reply->d_func();
1066 priv->manager = this;
1068 // second step: fetch cached credentials
1069 // This is not done for the time being, we should use signal emissions to request
1070 // the credentials from cache.
1072 // third step: find a backend
1073 priv->backend = d->findBackend(op, request);
1075 if (priv->backend) {
1076 priv->backend->setParent(reply);
1077 priv->backend->reply = priv;
1081 reply->setSslConfiguration(request.sslConfiguration());
1084 // fourth step: setup the reply
1085 priv->setup(op, request, outgoingData);
1094 Flushes the internal cache of authentication data and network connections.
1096 This function is useful for doing auto tests.
1099 void QNetworkAccessManager::clearAccessCache()
1101 QNetworkAccessManagerPrivate::clearCache(this);
1104 void QNetworkAccessManagerPrivate::_q_replyFinished()
1106 Q_Q(QNetworkAccessManager);
1108 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1110 emit q->finished(reply);
1112 #ifndef QT_NO_BEARERMANAGEMENT
1113 // If there are no active requests, release our reference to the network session.
1114 // It will not be destroyed immediately, but rather when the connection cache is flushed
1116 if (networkSession && q->findChildren<QNetworkReply *>().count() == 1)
1117 networkSession.clear();
1121 void QNetworkAccessManagerPrivate::_q_replySslErrors(const QList<QSslError> &errors)
1124 Q_Q(QNetworkAccessManager);
1125 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1127 emit q->sslErrors(reply, errors);
1133 QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
1135 Q_Q(QNetworkAccessManager);
1136 QNetworkReplyPrivate::setManager(reply, q);
1137 q->connect(reply, SIGNAL(finished()), SLOT(_q_replyFinished()));
1139 /* In case we're compiled without SSL support, we don't have this signal and we need to
1140 * avoid getting a connection error. */
1141 q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>)));
1147 void QNetworkAccessManagerPrivate::createCookieJar() const
1149 if (!cookieJarCreated) {
1150 // keep the ugly hack in here
1151 QNetworkAccessManagerPrivate *that = const_cast<QNetworkAccessManagerPrivate *>(this);
1152 that->cookieJar = new QNetworkCookieJar(that->q_func());
1153 that->cookieJarCreated = true;
1157 void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authenticator,
1158 QNetworkReply *reply,
1161 QUrl *urlForLastAuthentication,
1162 bool allowAuthenticationReuse)
1164 Q_Q(QNetworkAccessManager);
1166 // don't try the cache for the same URL twice in a row
1167 // being called twice for the same URL means the authentication failed
1168 // also called when last URL is empty, e.g. on first call
1169 if (allowAuthenticationReuse && (urlForLastAuthentication->isEmpty()
1170 || url != *urlForLastAuthentication)) {
1171 // if credentials are included in the url, then use them
1172 if (!url.userName().isEmpty()
1173 && !url.password().isEmpty()) {
1174 authenticator->setUser(url.userName());
1175 authenticator->setPassword(url.password());
1176 *urlForLastAuthentication = url;
1177 authenticationManager->cacheCredentials(url, authenticator);
1181 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
1182 if (!cred.isNull()) {
1183 authenticator->setUser(cred.user);
1184 authenticator->setPassword(cred.password);
1185 *urlForLastAuthentication = url;
1189 #if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
1190 //now we try to get the username and password from keychain
1191 //if not successful signal will be emitted
1194 if (getProxyAuth(proxy.hostName(),reply->request().url().scheme(),username,password)) {
1195 authenticator->setUser(username);
1196 authenticator->setPassword(password);
1197 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1202 // if we emit a signal here in synchronous mode, the user might spin
1203 // an event loop, which might recurse and lead to problems
1207 *urlForLastAuthentication = url;
1208 emit q->authenticationRequired(reply, authenticator);
1209 if (allowAuthenticationReuse)
1210 authenticationManager->cacheCredentials(url, authenticator);
1213 #ifndef QT_NO_NETWORKPROXY
1214 void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy,
1216 QAuthenticator *authenticator,
1217 QNetworkProxy *lastProxyAuthentication)
1219 Q_Q(QNetworkAccessManager);
1220 QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(*authenticator);
1221 if (proxy != *lastProxyAuthentication && (!priv || !priv->hasFailed)) {
1222 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1223 if (!cred.isNull()) {
1224 authenticator->setUser(cred.user);
1225 authenticator->setPassword(cred.password);
1230 // if we emit a signal here in synchronous mode, the user might spin
1231 // an event loop, which might recurse and lead to problems
1235 *lastProxyAuthentication = proxy;
1236 emit q->proxyAuthenticationRequired(proxy, authenticator);
1237 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1240 QList<QNetworkProxy> QNetworkAccessManagerPrivate::queryProxy(const QNetworkProxyQuery &query)
1242 QList<QNetworkProxy> proxies;
1244 proxies = proxyFactory->queryProxy(query);
1245 if (proxies.isEmpty()) {
1246 qWarning("QNetworkAccessManager: factory %p has returned an empty result set",
1248 proxies << QNetworkProxy::NoProxy;
1250 } else if (proxy.type() == QNetworkProxy::DefaultProxy) {
1251 // no proxy set, query the application
1252 return QNetworkProxyFactory::proxyForQuery(query);
1261 void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager)
1263 manager->d_func()->objectCache.clear();
1264 manager->d_func()->authenticationManager->clearCache();
1266 if (manager->d_func()->httpThread) {
1267 // The thread will deleteLater() itself from its finished() signal
1268 manager->d_func()->httpThread->quit();
1269 manager->d_func()->httpThread->wait(5000);
1270 manager->d_func()->httpThread = 0;
1274 QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
1277 // The thread will deleteLater() itself from its finished() signal
1279 httpThread->wait(5000);
1284 #ifndef QT_NO_BEARERMANAGEMENT
1285 void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &config)
1287 Q_Q(QNetworkAccessManager);
1289 initializeSession = false;
1291 QSharedPointer<QNetworkSession> newSession;
1292 if (config.isValid())
1293 newSession = QSharedNetworkSessionManager::getSession(config);
1295 if (networkSession) {
1296 //do nothing if new and old session are the same
1297 if (networkSession == newSession)
1299 //disconnect from old session
1300 QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()));
1301 QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()));
1302 QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
1303 q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)));
1306 //switch to new session (null if config was invalid)
1307 networkSession = newSession;
1309 if (!networkSession) {
1312 if (networkAccessible == QNetworkAccessManager::NotAccessible)
1313 emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
1315 emit q->networkAccessibleChanged(QNetworkAccessManager::UnknownAccessibility);
1320 //connect to new session
1321 QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection);
1322 //QueuedConnection is used to avoid deleting the networkSession inside its closed signal
1323 QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection);
1324 QObject::connect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
1325 q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
1327 _q_networkSessionStateChanged(networkSession->state());
1330 void QNetworkAccessManagerPrivate::_q_networkSessionClosed()
1332 Q_Q(QNetworkAccessManager);
1333 if (networkSession) {
1334 networkConfiguration = networkSession->configuration().identifier();
1336 //disconnect from old session
1337 QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()));
1338 QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()));
1339 QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
1340 q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)));
1341 networkSession.clear();
1345 void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession::State state)
1347 Q_Q(QNetworkAccessManager);
1349 //Do not emit the networkSessionConnected signal here, except for roaming -> connected
1350 //transition, otherwise it is emitted twice in a row when opening a connection.
1351 if (state == QNetworkSession::Connected && lastSessionState == QNetworkSession::Roaming)
1352 emit q->networkSessionConnected();
1353 lastSessionState = state;
1356 if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) {
1358 emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
1361 if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) {
1363 emit q->networkAccessibleChanged(networkAccessible);
1367 #endif // QT_NO_BEARERMANAGEMENT
1369 QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
1371 // copy the request, we probably need to add some headers
1372 QNetworkRequest newRequest(request);
1374 // add Content-Type header if not there already
1375 if (!request.header(QNetworkRequest::ContentTypeHeader).isValid()) {
1376 QByteArray contentType;
1377 contentType.reserve(34 + multiPart->d_func()->boundary.count());
1378 contentType += "multipart/";
1379 switch (multiPart->d_func()->contentType) {
1380 case QHttpMultiPart::RelatedType:
1381 contentType += "related";
1383 case QHttpMultiPart::FormDataType:
1384 contentType += "form-data";
1386 case QHttpMultiPart::AlternativeType:
1387 contentType += "alternative";
1390 contentType += "mixed";
1393 // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1
1394 contentType += "; boundary=\"" + multiPart->d_func()->boundary + "\"";
1395 newRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType));
1398 // add MIME-Version header if not there already (we must include the header
1399 // if the message conforms to RFC 2045, see section 4 of that RFC)
1400 QByteArray mimeHeader("MIME-Version");
1401 if (!request.hasRawHeader(mimeHeader))
1402 newRequest.setRawHeader(mimeHeader, QByteArray("1.0"));
1404 QIODevice *device = multiPart->d_func()->device;
1405 if (!device->isReadable()) {
1406 if (!device->isOpen()) {
1407 if (!device->open(QIODevice::ReadOnly))
1408 qWarning("could not open device for reading");
1410 qWarning("device is not readable");
1419 #include "moc_qnetworkaccessmanager.cpp"