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> >");
420 qRegisterMetaType<QHttpNetworkRequest>("QHttpNetworkRequest");
422 qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
423 qRegisterMetaType<QSharedPointer<char> >("QSharedPointer<char>");
427 Destroys the QNetworkAccessManager object and frees up any
428 resources. Note that QNetworkReply objects that are returned from
429 this class have this object set as their parents, which means that
430 they will be deleted along with it if you don't call
431 QObject::setParent() on them.
433 QNetworkAccessManager::~QNetworkAccessManager()
435 #ifndef QT_NO_NETWORKPROXY
436 delete d_func()->proxyFactory;
439 // Delete the QNetworkReply children first.
440 // Else a QAbstractNetworkCache might get deleted in ~QObject
441 // before a QNetworkReply that accesses the QAbstractNetworkCache
442 // object in its destructor.
443 qDeleteAll(findChildren<QNetworkReply *>());
444 // The other children will be deleted in this ~QObject
445 // FIXME instead of this "hack" make the QNetworkReplyImpl
446 // properly watch the cache deletion, e.g. via a QWeakPointer.
449 #ifndef QT_NO_NETWORKPROXY
451 Returns the QNetworkProxy that the requests sent using this
452 QNetworkAccessManager object will use. The default value for the
453 proxy is QNetworkProxy::DefaultProxy.
455 \sa setProxy(), setProxyFactory(), proxyAuthenticationRequired()
457 QNetworkProxy QNetworkAccessManager::proxy() const
459 return d_func()->proxy;
463 Sets the proxy to be used in future requests to be \a proxy. This
464 does not affect requests that have already been sent. The
465 proxyAuthenticationRequired() signal will be emitted if the proxy
466 requests authentication.
468 A proxy set with this function will be used for all requests
469 issued by QNetworkAccessManager. In some cases, it might be
470 necessary to select different proxies depending on the type of
471 request being sent or the destination host. If that's the case,
472 you should consider using setProxyFactory().
474 \sa proxy(), proxyAuthenticationRequired()
476 void QNetworkAccessManager::setProxy(const QNetworkProxy &proxy)
478 Q_D(QNetworkAccessManager);
479 delete d->proxyFactory;
485 \fn QNetworkProxyFactory *QNetworkAccessManager::proxyFactory() const
488 Returns the proxy factory that this QNetworkAccessManager object
489 is using to determine the proxies to be used for requests.
491 Note that the pointer returned by this function is managed by
492 QNetworkAccessManager and could be deleted at any time.
494 \sa setProxyFactory(), proxy()
496 QNetworkProxyFactory *QNetworkAccessManager::proxyFactory() const
498 return d_func()->proxyFactory;
504 Sets the proxy factory for this class to be \a factory. A proxy
505 factory is used to determine a more specific list of proxies to be
506 used for a given request, instead of trying to use the same proxy
507 value for all requests.
509 All queries sent by QNetworkAccessManager will have type
510 QNetworkProxyQuery::UrlRequest.
512 For example, a proxy factory could apply the following rules:
514 \li if the target address is in the local network (for example,
515 if the hostname contains no dots or if it's an IP address in
516 the organization's range), return QNetworkProxy::NoProxy
517 \li if the request is FTP, return an FTP proxy
518 \li if the request is HTTP or HTTPS, then return an HTTP proxy
519 \li otherwise, return a SOCKSv5 proxy server
522 The lifetime of the object \a factory will be managed by
523 QNetworkAccessManager. It will delete the object when necessary.
525 \note If a specific proxy is set with setProxy(), the factory will not
528 \sa proxyFactory(), setProxy(), QNetworkProxyQuery
530 void QNetworkAccessManager::setProxyFactory(QNetworkProxyFactory *factory)
532 Q_D(QNetworkAccessManager);
533 delete d->proxyFactory;
534 d->proxyFactory = factory;
535 d->proxy = QNetworkProxy();
542 Returns the cache that is used to store data obtained from the network.
546 QAbstractNetworkCache *QNetworkAccessManager::cache() const
548 Q_D(const QNetworkAccessManager);
549 return d->networkCache;
555 Sets the manager's network cache to be the \a cache specified. The cache
556 is used for all requests dispatched by the manager.
558 Use this function to set the network cache object to a class that implements
559 additional features, like saving the cookies to permanent storage.
561 \note QNetworkAccessManager takes ownership of the \a cache object.
563 QNetworkAccessManager by default does not have a set cache.
564 Qt provides a simple disk cache, QNetworkDiskCache, which can be used.
566 \sa cache(), QNetworkRequest::CacheLoadControl
568 void QNetworkAccessManager::setCache(QAbstractNetworkCache *cache)
570 Q_D(QNetworkAccessManager);
571 if (d->networkCache != cache) {
572 delete d->networkCache;
573 d->networkCache = cache;
575 d->networkCache->setParent(this);
580 Returns the QNetworkCookieJar that is used to store cookies
581 obtained from the network as well as cookies that are about to be
586 QNetworkCookieJar *QNetworkAccessManager::cookieJar() const
588 Q_D(const QNetworkAccessManager);
590 d->createCookieJar();
595 Sets the manager's cookie jar to be the \a cookieJar specified.
596 The cookie jar is used by all requests dispatched by the manager.
598 Use this function to set the cookie jar object to a class that
599 implements additional features, like saving the cookies to permanent
602 \note QNetworkAccessManager takes ownership of the \a cookieJar object.
604 If \a cookieJar is in the same thread as this QNetworkAccessManager,
605 it will set the parent of the \a cookieJar
606 so that the cookie jar is deleted when this
607 object is deleted as well. If you want to share cookie jars
608 between different QNetworkAccessManager objects, you may want to
609 set the cookie jar's parent to 0 after calling this function.
611 QNetworkAccessManager by default does not implement any cookie
612 policy of its own: it accepts all cookies sent by the server, as
613 long as they are well formed and meet the minimum security
614 requirements (cookie domain matches the request's and cookie path
615 matches the request's). In order to implement your own security
616 policy, override the QNetworkCookieJar::cookiesForUrl() and
617 QNetworkCookieJar::setCookiesFromUrl() virtual functions. Those
618 functions are called by QNetworkAccessManager when it detects a
621 \sa cookieJar(), QNetworkCookieJar::cookiesForUrl(), QNetworkCookieJar::setCookiesFromUrl()
623 void QNetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
625 Q_D(QNetworkAccessManager);
626 d->cookieJarCreated = true;
627 if (d->cookieJar != cookieJar) {
628 if (d->cookieJar && d->cookieJar->parent() == this)
630 d->cookieJar = cookieJar;
631 if (thread() == cookieJar->thread())
632 d->cookieJar->setParent(this);
637 Posts a request to obtain the network headers for \a request
638 and returns a new QNetworkReply object which will contain such headers.
640 The function is named after the HTTP request associated (HEAD).
642 QNetworkReply *QNetworkAccessManager::head(const QNetworkRequest &request)
644 return d_func()->postProcess(createRequest(QNetworkAccessManager::HeadOperation, request));
648 Posts a request to obtain the contents of the target \a request
649 and returns a new QNetworkReply object opened for reading which emits the
650 \l{QIODevice::readyRead()}{readyRead()} signal whenever new data
653 The contents as well as associated headers will be downloaded.
655 \sa post(), put(), deleteResource(), sendCustomRequest()
657 QNetworkReply *QNetworkAccessManager::get(const QNetworkRequest &request)
659 return d_func()->postProcess(createRequest(QNetworkAccessManager::GetOperation, request));
663 Sends an HTTP POST request to the destination specified by \a request
664 and returns a new QNetworkReply object opened for reading that will
665 contain the reply sent by the server. The contents of the \a data
666 device will be uploaded to the server.
668 \a data must be open for reading and must remain valid until the
669 finished() signal is emitted for this reply.
671 \note Sending a POST request on protocols other than HTTP and
672 HTTPS is undefined and will probably fail.
674 \sa get(), put(), deleteResource(), sendCustomRequest()
676 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data)
678 return d_func()->postProcess(createRequest(QNetworkAccessManager::PostOperation, request, data));
684 Sends the contents of the \a data byte array to the destination
685 specified by \a request.
687 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, const QByteArray &data)
689 QBuffer *buffer = new QBuffer;
690 buffer->setData(data);
691 buffer->open(QIODevice::ReadOnly);
693 QNetworkReply *reply = post(request, buffer);
694 buffer->setParent(reply);
703 Sends the contents of the \a multiPart message to the destination
704 specified by \a request.
706 This can be used for sending MIME multipart messages over HTTP.
708 \sa QHttpMultiPart, QHttpPart, put()
710 QNetworkReply *QNetworkAccessManager::post(const QNetworkRequest &request, QHttpMultiPart *multiPart)
712 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
713 QIODevice *device = multiPart->d_func()->device;
714 QNetworkReply *reply = post(newRequest, device);
723 Sends the contents of the \a multiPart message to the destination
724 specified by \a request.
726 This can be used for sending MIME multipart messages over HTTP.
728 \sa QHttpMultiPart, QHttpPart, post()
730 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QHttpMultiPart *multiPart)
732 QNetworkRequest newRequest = d_func()->prepareMultipart(request, multiPart);
733 QIODevice *device = multiPart->d_func()->device;
734 QNetworkReply *reply = put(newRequest, device);
739 Uploads the contents of \a data to the destination \a request and
740 returnes a new QNetworkReply object that will be open for reply.
742 \a data must be opened for reading when this function is called
743 and must remain valid until the finished() signal is emitted for
746 Whether anything will be available for reading from the returned
747 object is protocol dependent. For HTTP, the server may send a
748 small HTML page indicating the upload was successful (or not).
749 Other protocols will probably have content in their replies.
751 \note For HTTP, this request will send a PUT request, which most servers
752 do not allow. Form upload mechanisms, including that of uploading
753 files through HTML forms, use the POST mechanism.
755 \sa get(), post(), deleteResource(), sendCustomRequest()
757 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, QIODevice *data)
759 return d_func()->postProcess(createRequest(QNetworkAccessManager::PutOperation, request, data));
765 Sends the contents of the \a data byte array to the destination
766 specified by \a request.
768 QNetworkReply *QNetworkAccessManager::put(const QNetworkRequest &request, const QByteArray &data)
770 QBuffer *buffer = new QBuffer;
771 buffer->setData(data);
772 buffer->open(QIODevice::ReadOnly);
774 QNetworkReply *reply = put(request, buffer);
775 buffer->setParent(reply);
782 Sends a request to delete the resource identified by the URL of \a request.
784 \note This feature is currently available for HTTP only, performing an
787 \sa get(), post(), put(), sendCustomRequest()
789 QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &request)
791 return d_func()->postProcess(createRequest(QNetworkAccessManager::DeleteOperation, request));
794 #ifndef QT_NO_BEARERMANAGEMENT
799 Sets the network configuration that will be used when creating the
800 \l {QNetworkSession}{network session} to \a config.
802 The network configuration is used to create and open a network session before any request that
803 requires network access is process. If no network configuration is explicitly set via this
804 function the network configuration returned by
805 QNetworkConfigurationManager::defaultConfiguration() will be used.
807 To restore the default network configuration set the network configuration to the value
808 returned from QNetworkConfigurationManager::defaultConfiguration().
810 \snippet code/src_network_access_qnetworkaccessmanager.cpp 2
812 If an invalid network configuration is set, a network session will not be created. In this
813 case network requests will be processed regardless, but may fail. For example:
815 \snippet code/src_network_access_qnetworkaccessmanager.cpp 3
817 \sa configuration(), QNetworkSession
819 void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config)
821 d_func()->createSession(config);
827 Returns the network configuration that will be used to create the
828 \l {QNetworkSession}{network session} which will be used when processing network requests.
830 \sa setConfiguration(), activeConfiguration()
832 QNetworkConfiguration QNetworkAccessManager::configuration() const
834 Q_D(const QNetworkAccessManager);
836 QSharedPointer<QNetworkSession> session(d->getNetworkSession());
838 return session->configuration();
840 return QNetworkConfiguration();
846 Returns the current active network configuration.
848 If the network configuration returned by configuration() is of type
849 QNetworkConfiguration::ServiceNetwork this function will return the current active child
850 network configuration of that configuration. Otherwise returns the same network configuration
853 Use this function to return the actual network configuration currently in use by the network
858 QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
860 Q_D(const QNetworkAccessManager);
862 QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
863 if (networkSession) {
864 QNetworkConfigurationManager manager;
866 return manager.configurationFromIdentifier(
867 networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString());
869 return QNetworkConfiguration();
876 Overrides the reported network accessibility. If \a accessible is NotAccessible the reported
877 network accessiblity will always be NotAccessible. Otherwise the reported network
878 accessibility will reflect the actual device state.
880 void QNetworkAccessManager::setNetworkAccessible(QNetworkAccessManager::NetworkAccessibility accessible)
882 Q_D(QNetworkAccessManager);
884 if (d->networkAccessible != accessible) {
885 NetworkAccessibility previous = networkAccessible();
886 d->networkAccessible = accessible;
887 NetworkAccessibility current = networkAccessible();
888 if (previous != current)
889 emit networkAccessibleChanged(current);
896 Returns the current network accessibility.
898 QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccessible() const
900 Q_D(const QNetworkAccessManager);
902 QSharedPointer<QNetworkSession> networkSession(d->getNetworkSession());
903 if (networkSession) {
904 // d->online holds online/offline state of this network session.
906 return d->networkAccessible;
908 return NotAccessible;
910 // Network accessibility is either disabled or unknown.
911 return (d->networkAccessible == NotAccessible) ? NotAccessible : UnknownAccessibility;
918 Returns the network session currently in use.
919 This can be changed at any time, ownership remains with the QNetworkAccessManager
921 const QWeakPointer<const QNetworkSession> QNetworkAccessManagerPrivate::getNetworkSession(const QNetworkAccessManager *q)
923 return q->d_func()->networkSessionWeakRef;
926 QSharedPointer<QNetworkSession> QNetworkAccessManagerPrivate::getNetworkSession() const
928 if (networkSessionStrongRef)
929 return networkSessionStrongRef;
930 return networkSessionWeakRef.toStrongRef();
933 #endif // QT_NO_BEARERMANAGEMENT
938 Sends a custom request to the server identified by the URL of \a request.
940 It is the user's responsibility to send a \a verb to the server that is valid
941 according to the HTTP specification.
943 This method provides means to send verbs other than the common ones provided
944 via get() or post() etc., for instance sending an HTTP OPTIONS command.
946 If \a data is not empty, the contents of the \a data
947 device will be uploaded to the server; in that case, data must be open for
948 reading and must remain valid until the finished() signal is emitted for this reply.
950 \note This feature is currently available for HTTP(S) only.
952 \sa get(), post(), put(), deleteResource()
954 QNetworkReply *QNetworkAccessManager::sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data)
956 QNetworkRequest newRequest(request);
957 newRequest.setAttribute(QNetworkRequest::CustomVerbAttribute, verb);
958 return d_func()->postProcess(createRequest(QNetworkAccessManager::CustomOperation, newRequest, data));
962 Returns a new QNetworkReply object to handle the operation \a op
963 and request \a req. The device \a outgoingData is always 0 for Get and
964 Head requests, but is the value passed to post() and put() in
965 those operations (the QByteArray variants will pass a QBuffer
968 The default implementation calls QNetworkCookieJar::cookiesForUrl()
969 on the cookie jar set with setCookieJar() to obtain the cookies to
970 be sent to the remote server.
972 The returned object must be in an open state.
974 QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op,
975 const QNetworkRequest &req,
976 QIODevice *outgoingData)
978 Q_D(QNetworkAccessManager);
980 bool isLocalFile = req.url().isLocalFile();
981 QString scheme = req.url().scheme().toLower();
983 // fast path for GET on file:// URLs
984 // The QNetworkAccessFileBackend will right now only be used for PUT
985 if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
986 && (isLocalFile || scheme == QLatin1String("qrc"))) {
987 return new QNetworkReplyFileImpl(this, req, op);
990 if ((op == QNetworkAccessManager::GetOperation || op == QNetworkAccessManager::HeadOperation)
991 && scheme == QLatin1String("data")) {
992 return new QNetworkReplyDataImpl(this, req, op);
995 // A request with QNetworkRequest::AlwaysCache does not need any bearer management
996 QNetworkRequest::CacheLoadControl mode =
997 static_cast<QNetworkRequest::CacheLoadControl>(
998 req.attribute(QNetworkRequest::CacheLoadControlAttribute,
999 QNetworkRequest::PreferNetwork).toInt());
1000 if (mode == QNetworkRequest::AlwaysCache
1001 && (op == QNetworkAccessManager::GetOperation
1002 || op == QNetworkAccessManager::HeadOperation)) {
1003 // FIXME Implement a QNetworkReplyCacheImpl instead, see QTBUG-15106
1004 QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
1005 QNetworkReplyImplPrivate *priv = reply->d_func();
1006 priv->manager = this;
1007 priv->backend = new QNetworkAccessCacheBackend();
1008 priv->backend->manager = this->d_func();
1009 priv->backend->setParent(reply);
1010 priv->backend->reply = priv;
1011 priv->setup(op, req, outgoingData);
1015 #ifndef QT_NO_BEARERMANAGEMENT
1016 // Return a disabled network reply if network access is disabled.
1017 // Except if the scheme is empty or file://.
1018 if (!d->networkAccessible && !isLocalFile) {
1019 return new QDisabledNetworkReply(this, req, op);
1022 if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.isEmpty())) {
1023 QNetworkConfigurationManager manager;
1024 if (!d->networkConfiguration.isEmpty()) {
1025 d->createSession(manager.configurationFromIdentifier(d->networkConfiguration));
1027 if (manager.capabilities() & QNetworkConfigurationManager::NetworkSessionRequired)
1028 d->createSession(manager.defaultConfiguration());
1030 d->initializeSession = false;
1035 QNetworkRequest request = req;
1036 if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() &&
1037 outgoingData && !outgoingData->isSequential()) {
1038 // request has no Content-Length
1039 // but the data that is outgoing is random-access
1040 request.setHeader(QNetworkRequest::ContentLengthHeader, outgoingData->size());
1043 if (static_cast<QNetworkRequest::LoadControl>
1044 (request.attribute(QNetworkRequest::CookieLoadControlAttribute,
1045 QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Automatic) {
1047 QList<QNetworkCookie> cookies = d->cookieJar->cookiesForUrl(request.url());
1048 if (!cookies.isEmpty())
1049 request.setHeader(QNetworkRequest::CookieHeader, QVariant::fromValue(cookies));
1054 // Since Qt 5 we use the new QNetworkReplyHttpImpl
1055 if (scheme == QLatin1String("http")
1057 || scheme == QLatin1String("https")
1060 QNetworkReplyHttpImpl *reply = new QNetworkReplyHttpImpl(this, request, op, outgoingData);
1061 #ifndef QT_NO_BEARERMANAGEMENT
1062 connect(this, SIGNAL(networkSessionConnected()),
1063 reply, SLOT(_q_networkSessionConnected()));
1067 #endif // QT_NO_HTTP
1069 // first step: create the reply
1070 QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
1071 #ifndef QT_NO_BEARERMANAGEMENT
1073 connect(this, SIGNAL(networkSessionConnected()),
1074 reply, SLOT(_q_networkSessionConnected()));
1077 QNetworkReplyImplPrivate *priv = reply->d_func();
1078 priv->manager = this;
1080 // second step: fetch cached credentials
1081 // This is not done for the time being, we should use signal emissions to request
1082 // the credentials from cache.
1084 // third step: find a backend
1085 priv->backend = d->findBackend(op, request);
1087 if (priv->backend) {
1088 priv->backend->setParent(reply);
1089 priv->backend->reply = priv;
1093 reply->setSslConfiguration(request.sslConfiguration());
1096 // fourth step: setup the reply
1097 priv->setup(op, request, outgoingData);
1106 Flushes the internal cache of authentication data and network connections.
1108 This function is useful for doing auto tests.
1111 void QNetworkAccessManager::clearAccessCache()
1113 QNetworkAccessManagerPrivate::clearCache(this);
1116 void QNetworkAccessManagerPrivate::_q_replyFinished()
1118 Q_Q(QNetworkAccessManager);
1120 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1122 emit q->finished(reply);
1124 #ifndef QT_NO_BEARERMANAGEMENT
1125 // If there are no active requests, release our reference to the network session.
1126 // It will not be destroyed immediately, but rather when the connection cache is flushed
1129 if (networkSessionStrongRef && activeReplyCount == 0)
1130 networkSessionStrongRef.clear();
1134 void QNetworkAccessManagerPrivate::_q_replySslErrors(const QList<QSslError> &errors)
1137 Q_Q(QNetworkAccessManager);
1138 QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
1140 emit q->sslErrors(reply, errors);
1146 QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply)
1148 Q_Q(QNetworkAccessManager);
1149 QNetworkReplyPrivate::setManager(reply, q);
1150 q->connect(reply, SIGNAL(finished()), SLOT(_q_replyFinished()));
1152 /* In case we're compiled without SSL support, we don't have this signal and we need to
1153 * avoid getting a connection error. */
1154 q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>)));
1156 #ifndef QT_NO_BEARERMANAGEMENT
1163 void QNetworkAccessManagerPrivate::createCookieJar() const
1165 if (!cookieJarCreated) {
1166 // keep the ugly hack in here
1167 QNetworkAccessManagerPrivate *that = const_cast<QNetworkAccessManagerPrivate *>(this);
1168 that->cookieJar = new QNetworkCookieJar(that->q_func());
1169 that->cookieJarCreated = true;
1173 void QNetworkAccessManagerPrivate::authenticationRequired(QAuthenticator *authenticator,
1174 QNetworkReply *reply,
1177 QUrl *urlForLastAuthentication,
1178 bool allowAuthenticationReuse)
1180 Q_Q(QNetworkAccessManager);
1182 // don't try the cache for the same URL twice in a row
1183 // being called twice for the same URL means the authentication failed
1184 // also called when last URL is empty, e.g. on first call
1185 if (allowAuthenticationReuse && (urlForLastAuthentication->isEmpty()
1186 || url != *urlForLastAuthentication)) {
1187 // if credentials are included in the url, then use them
1188 if (!url.userName().isEmpty()
1189 && !url.password().isEmpty()) {
1190 authenticator->setUser(url.userName());
1191 authenticator->setPassword(url.password());
1192 *urlForLastAuthentication = url;
1193 authenticationManager->cacheCredentials(url, authenticator);
1197 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedCredentials(url, authenticator);
1198 if (!cred.isNull()) {
1199 authenticator->setUser(cred.user);
1200 authenticator->setPassword(cred.password);
1201 *urlForLastAuthentication = url;
1205 #if defined(Q_OS_MAC) && !defined(Q_OS_IOS)
1206 //now we try to get the username and password from keychain
1207 //if not successful signal will be emitted
1210 if (getProxyAuth(proxy.hostName(),reply->request().url().scheme(),username,password)) {
1211 authenticator->setUser(username);
1212 authenticator->setPassword(password);
1213 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1218 // if we emit a signal here in synchronous mode, the user might spin
1219 // an event loop, which might recurse and lead to problems
1223 *urlForLastAuthentication = url;
1224 emit q->authenticationRequired(reply, authenticator);
1225 if (allowAuthenticationReuse)
1226 authenticationManager->cacheCredentials(url, authenticator);
1229 #ifndef QT_NO_NETWORKPROXY
1230 void QNetworkAccessManagerPrivate::proxyAuthenticationRequired(const QNetworkProxy &proxy,
1232 QAuthenticator *authenticator,
1233 QNetworkProxy *lastProxyAuthentication)
1235 Q_Q(QNetworkAccessManager);
1236 QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(*authenticator);
1237 if (proxy != *lastProxyAuthentication && (!priv || !priv->hasFailed)) {
1238 QNetworkAuthenticationCredential cred = authenticationManager->fetchCachedProxyCredentials(proxy);
1239 if (!cred.isNull()) {
1240 authenticator->setUser(cred.user);
1241 authenticator->setPassword(cred.password);
1246 // if we emit a signal here in synchronous mode, the user might spin
1247 // an event loop, which might recurse and lead to problems
1251 *lastProxyAuthentication = proxy;
1252 emit q->proxyAuthenticationRequired(proxy, authenticator);
1253 authenticationManager->cacheProxyCredentials(proxy, authenticator);
1256 QList<QNetworkProxy> QNetworkAccessManagerPrivate::queryProxy(const QNetworkProxyQuery &query)
1258 QList<QNetworkProxy> proxies;
1260 proxies = proxyFactory->queryProxy(query);
1261 if (proxies.isEmpty()) {
1262 qWarning("QNetworkAccessManager: factory %p has returned an empty result set",
1264 proxies << QNetworkProxy::NoProxy;
1266 } else if (proxy.type() == QNetworkProxy::DefaultProxy) {
1267 // no proxy set, query the application
1268 return QNetworkProxyFactory::proxyForQuery(query);
1277 void QNetworkAccessManagerPrivate::clearCache(QNetworkAccessManager *manager)
1279 manager->d_func()->objectCache.clear();
1280 manager->d_func()->authenticationManager->clearCache();
1282 if (manager->d_func()->httpThread) {
1283 // The thread will deleteLater() itself from its finished() signal
1284 manager->d_func()->httpThread->quit();
1285 manager->d_func()->httpThread->wait(5000);
1286 manager->d_func()->httpThread = 0;
1290 QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
1293 // The thread will deleteLater() itself from its finished() signal
1295 httpThread->wait(5000);
1300 #ifndef QT_NO_BEARERMANAGEMENT
1301 void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &config)
1303 Q_Q(QNetworkAccessManager);
1305 initializeSession = false;
1307 //resurrect weak ref if possible
1308 networkSessionStrongRef = networkSessionWeakRef.toStrongRef();
1310 QSharedPointer<QNetworkSession> newSession;
1311 if (config.isValid())
1312 newSession = QSharedNetworkSessionManager::getSession(config);
1314 if (networkSessionStrongRef) {
1315 //do nothing if new and old session are the same
1316 if (networkSessionStrongRef == newSession)
1318 //disconnect from old session
1319 QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()));
1320 QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()));
1321 QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(stateChanged(QNetworkSession::State)),
1322 q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)));
1325 //switch to new session (null if config was invalid)
1326 networkSessionStrongRef = newSession;
1327 networkSessionWeakRef = networkSessionStrongRef.toWeakRef();
1329 if (!networkSessionStrongRef) {
1332 if (networkAccessible == QNetworkAccessManager::NotAccessible)
1333 emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
1335 emit q->networkAccessibleChanged(QNetworkAccessManager::UnknownAccessibility);
1340 //connect to new session
1341 QObject::connect(networkSessionStrongRef.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection);
1342 //QueuedConnection is used to avoid deleting the networkSession inside its closed signal
1343 QObject::connect(networkSessionStrongRef.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection);
1344 QObject::connect(networkSessionStrongRef.data(), SIGNAL(stateChanged(QNetworkSession::State)),
1345 q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection);
1347 _q_networkSessionStateChanged(networkSessionStrongRef->state());
1350 void QNetworkAccessManagerPrivate::_q_networkSessionClosed()
1352 Q_Q(QNetworkAccessManager);
1353 QSharedPointer<QNetworkSession> networkSession(getNetworkSession());
1354 if (networkSession) {
1355 networkConfiguration = networkSession->configuration().identifier();
1357 //disconnect from old session
1358 QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()));
1359 QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()));
1360 QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)),
1361 q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)));
1362 networkSessionStrongRef.clear();
1363 networkSessionWeakRef.clear();
1367 void QNetworkAccessManagerPrivate::_q_networkSessionStateChanged(QNetworkSession::State state)
1369 Q_Q(QNetworkAccessManager);
1371 //Do not emit the networkSessionConnected signal here, except for roaming -> connected
1372 //transition, otherwise it is emitted twice in a row when opening a connection.
1373 if (state == QNetworkSession::Connected && lastSessionState == QNetworkSession::Roaming)
1374 emit q->networkSessionConnected();
1375 lastSessionState = state;
1378 if (state != QNetworkSession::Connected && state != QNetworkSession::Roaming) {
1380 emit q->networkAccessibleChanged(QNetworkAccessManager::NotAccessible);
1383 if (state == QNetworkSession::Connected || state == QNetworkSession::Roaming) {
1385 emit q->networkAccessibleChanged(networkAccessible);
1389 #endif // QT_NO_BEARERMANAGEMENT
1391 QNetworkRequest QNetworkAccessManagerPrivate::prepareMultipart(const QNetworkRequest &request, QHttpMultiPart *multiPart)
1393 // copy the request, we probably need to add some headers
1394 QNetworkRequest newRequest(request);
1396 // add Content-Type header if not there already
1397 if (!request.header(QNetworkRequest::ContentTypeHeader).isValid()) {
1398 QByteArray contentType;
1399 contentType.reserve(34 + multiPart->d_func()->boundary.count());
1400 contentType += "multipart/";
1401 switch (multiPart->d_func()->contentType) {
1402 case QHttpMultiPart::RelatedType:
1403 contentType += "related";
1405 case QHttpMultiPart::FormDataType:
1406 contentType += "form-data";
1408 case QHttpMultiPart::AlternativeType:
1409 contentType += "alternative";
1412 contentType += "mixed";
1415 // putting the boundary into quotes, recommended in RFC 2046 section 5.1.1
1416 contentType += "; boundary=\"" + multiPart->d_func()->boundary + "\"";
1417 newRequest.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(contentType));
1420 // add MIME-Version header if not there already (we must include the header
1421 // if the message conforms to RFC 2045, see section 4 of that RFC)
1422 QByteArray mimeHeader("MIME-Version");
1423 if (!request.hasRawHeader(mimeHeader))
1424 newRequest.setRawHeader(mimeHeader, QByteArray("1.0"));
1426 QIODevice *device = multiPart->d_func()->device;
1427 if (!device->isReadable()) {
1428 if (!device->isOpen()) {
1429 if (!device->open(QIODevice::ReadOnly))
1430 qWarning("could not open device for reading");
1432 qWarning("device is not readable");
1441 #include "moc_qnetworkaccessmanager.cpp"