src/network/access/qnetworkaccesshttpbackend.cpp
changeset 30 5dc02b23752f
parent 23 89e065397ea6
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
   211     case QNetworkAccessManager::GetOperation:
   211     case QNetworkAccessManager::GetOperation:
   212     case QNetworkAccessManager::PostOperation:
   212     case QNetworkAccessManager::PostOperation:
   213     case QNetworkAccessManager::HeadOperation:
   213     case QNetworkAccessManager::HeadOperation:
   214     case QNetworkAccessManager::PutOperation:
   214     case QNetworkAccessManager::PutOperation:
   215     case QNetworkAccessManager::DeleteOperation:
   215     case QNetworkAccessManager::DeleteOperation:
       
   216     case QNetworkAccessManager::CustomOperation:
   216         break;
   217         break;
   217 
   218 
   218     default:
   219     default:
   219         // no, we can't handle this request
   220         // no, we can't handle this request
   220         return 0;
   221         return 0;
   294 QNetworkAccessHttpBackend::QNetworkAccessHttpBackend()
   295 QNetworkAccessHttpBackend::QNetworkAccessHttpBackend()
   295     : QNetworkAccessBackend(), httpReply(0), http(0), uploadDevice(0)
   296     : QNetworkAccessBackend(), httpReply(0), http(0), uploadDevice(0)
   296 #ifndef QT_NO_OPENSSL
   297 #ifndef QT_NO_OPENSSL
   297     , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
   298     , pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
   298 #endif
   299 #endif
       
   300     , resumeOffset(0)
   299 {
   301 {
   300 }
   302 }
   301 
   303 
   302 QNetworkAccessHttpBackend::~QNetworkAccessHttpBackend()
   304 QNetworkAccessHttpBackend::~QNetworkAccessHttpBackend()
   303 {
   305 {
   342     connect(http, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
   344     connect(http, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
   343             SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
   345             SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
   344 #endif
   346 #endif
   345     connect(http, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
   347     connect(http, SIGNAL(authenticationRequired(QHttpNetworkRequest,QAuthenticator*)),
   346             SLOT(httpAuthenticationRequired(QHttpNetworkRequest,QAuthenticator*)));
   348             SLOT(httpAuthenticationRequired(QHttpNetworkRequest,QAuthenticator*)));
       
   349     connect(http, SIGNAL(cacheCredentials(QHttpNetworkRequest,QAuthenticator*)),
       
   350             SLOT(httpCacheCredentials(QHttpNetworkRequest,QAuthenticator*)));
   347     connect(http, SIGNAL(error(QNetworkReply::NetworkError,QString)),
   351     connect(http, SIGNAL(error(QNetworkReply::NetworkError,QString)),
   348             SLOT(httpError(QNetworkReply::NetworkError,QString)));
   352             SLOT(httpError(QNetworkReply::NetworkError,QString)));
   349 #ifndef QT_NO_OPENSSL
   353 #ifndef QT_NO_OPENSSL
   350     connect(http, SIGNAL(sslErrors(QList<QSslError>)),
   354     connect(http, SIGNAL(sslErrors(QList<QSslError>)),
   351             SLOT(sslErrors(QList<QSslError>)));
   355             SLOT(sslErrors(QList<QSslError>)));
   478 #endif
   482 #endif
   479     if (!sendCacheContents(metaData))
   483     if (!sendCacheContents(metaData))
   480         loadedFromCache = false;
   484         loadedFromCache = false;
   481 }
   485 }
   482 
   486 
       
   487 static QHttpNetworkRequest::Priority convert(const QNetworkRequest::Priority& prio)
       
   488 {
       
   489     switch (prio) {
       
   490     case QNetworkRequest::LowPriority:
       
   491         return QHttpNetworkRequest::LowPriority;
       
   492     case QNetworkRequest::HighPriority:
       
   493         return QHttpNetworkRequest::HighPriority;
       
   494     case QNetworkRequest::NormalPriority:
       
   495     default:
       
   496         return QHttpNetworkRequest::NormalPriority;
       
   497     }
       
   498 }
       
   499 
   483 void QNetworkAccessHttpBackend::postRequest()
   500 void QNetworkAccessHttpBackend::postRequest()
   484 {
   501 {
   485     bool loadedFromCache = false;
   502     bool loadedFromCache = false;
   486     QHttpNetworkRequest httpRequest;
   503     QHttpNetworkRequest httpRequest;
       
   504     httpRequest.setPriority(convert(request().priority()));
   487     switch (operation()) {
   505     switch (operation()) {
   488     case QNetworkAccessManager::GetOperation:
   506     case QNetworkAccessManager::GetOperation:
   489         httpRequest.setOperation(QHttpNetworkRequest::Get);
   507         httpRequest.setOperation(QHttpNetworkRequest::Get);
   490         validateCache(httpRequest, loadedFromCache);
   508         validateCache(httpRequest, loadedFromCache);
   491         break;
   509         break;
   510     case QNetworkAccessManager::DeleteOperation:
   528     case QNetworkAccessManager::DeleteOperation:
   511         invalidateCache();
   529         invalidateCache();
   512         httpRequest.setOperation(QHttpNetworkRequest::Delete);
   530         httpRequest.setOperation(QHttpNetworkRequest::Delete);
   513         break;
   531         break;
   514 
   532 
       
   533     case QNetworkAccessManager::CustomOperation:
       
   534         invalidateCache(); // for safety reasons, we don't know what the operation does
       
   535         httpRequest.setOperation(QHttpNetworkRequest::Custom);
       
   536         httpRequest.setUploadByteDevice(createUploadByteDevice());
       
   537         httpRequest.setCustomVerb(request().attribute(
       
   538                 QNetworkRequest::CustomVerbAttribute).toByteArray());
       
   539         break;
       
   540 
   515     default:
   541     default:
   516         break;                  // can't happen
   542         break;                  // can't happen
   517     }
   543     }
   518 
   544 
   519     httpRequest.setUrl(url());
   545     httpRequest.setUrl(url());
   520 
   546 
   521     QList<QByteArray> headers = request().rawHeaderList();
   547     QList<QByteArray> headers = request().rawHeaderList();
       
   548     if (resumeOffset != 0) {
       
   549         if (headers.contains("Range")) {
       
   550             // Need to adjust resume offset for user specified range
       
   551 
       
   552             headers.removeOne("Range");
       
   553 
       
   554             // We've already verified that requestRange starts with "bytes=", see canResume.
       
   555             QByteArray requestRange = request().rawHeader("Range").mid(6);
       
   556 
       
   557             int index = requestRange.indexOf('-');
       
   558 
       
   559             quint64 requestStartOffset = requestRange.left(index).toULongLong();
       
   560             quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong();
       
   561 
       
   562             requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) +
       
   563                            '-' + QByteArray::number(requestEndOffset);
       
   564 
       
   565             httpRequest.setHeaderField("Range", requestRange);
       
   566         } else {
       
   567             httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-');
       
   568         }
       
   569     }
   522     foreach (const QByteArray &header, headers)
   570     foreach (const QByteArray &header, headers)
   523         httpRequest.setHeaderField(header, request().rawHeader(header));
   571         httpRequest.setHeaderField(header, request().rawHeader(header));
   524 
   572 
   525     if (loadedFromCache) {
   573     if (loadedFromCache) {
   526         // commented this out since it will be called later anyway
   574         // commented this out since it will be called later anyway
   529         return;    // no need to send the request! :)
   577         return;    // no need to send the request! :)
   530     }
   578     }
   531 
   579 
   532     if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true)
   580     if (request().attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool() == true)
   533         httpRequest.setPipeliningAllowed(true);
   581         httpRequest.setPipeliningAllowed(true);
       
   582 
       
   583     if (static_cast<QNetworkRequest::LoadControl>
       
   584         (request().attribute(QNetworkRequest::AuthenticationReuseAttribute,
       
   585                              QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Manual)
       
   586         httpRequest.setWithCredentials(false);
   534 
   587 
   535     httpReply = http->sendRequest(httpRequest);
   588     httpReply = http->sendRequest(httpRequest);
   536     httpReply->setParent(this);
   589     httpReply->setParent(this);
   537 #ifndef QT_NO_OPENSSL
   590 #ifndef QT_NO_OPENSSL
   538     if (pendingSslConfiguration)
   591     if (pendingSslConfiguration)
   811 
   864 
   812 void QNetworkAccessHttpBackend::httpAuthenticationRequired(const QHttpNetworkRequest &,
   865 void QNetworkAccessHttpBackend::httpAuthenticationRequired(const QHttpNetworkRequest &,
   813                                                            QAuthenticator *auth)
   866                                                            QAuthenticator *auth)
   814 {
   867 {
   815     authenticationRequired(auth);
   868     authenticationRequired(auth);
       
   869 }
       
   870 
       
   871 void QNetworkAccessHttpBackend::httpCacheCredentials(const QHttpNetworkRequest &,
       
   872                                                  QAuthenticator *auth)
       
   873 {
       
   874     cacheCredentials(auth);
   816 }
   875 }
   817 
   876 
   818 void QNetworkAccessHttpBackend::httpError(QNetworkReply::NetworkError errorCode,
   877 void QNetworkAccessHttpBackend::httpError(QNetworkReply::NetworkError errorCode,
   819                                           const QString &errorString)
   878                                           const QString &errorString)
   820 {
   879 {
  1091     }
  1150     }
  1092     metaData.setAttributes(attributes);
  1151     metaData.setAttributes(attributes);
  1093     return metaData;
  1152     return metaData;
  1094 }
  1153 }
  1095 
  1154 
       
  1155 bool QNetworkAccessHttpBackend::canResume() const
       
  1156 {
       
  1157     // Only GET operation supports resuming.
       
  1158     if (operation() != QNetworkAccessManager::GetOperation)
       
  1159         return false;
       
  1160 
       
  1161     // Can only resume if server/resource supports Range header.
       
  1162     if (httpReply->headerField("Accept-Ranges", "none") == "none")
       
  1163         return false;
       
  1164 
       
  1165     // We only support resuming for byte ranges.
       
  1166     if (request().hasRawHeader("Range")) {
       
  1167         QByteArray range = request().rawHeader("Range");
       
  1168         if (!range.startsWith("bytes="))
       
  1169             return false;
       
  1170     }
       
  1171 
       
  1172     return true;
       
  1173 }
       
  1174 
       
  1175 void QNetworkAccessHttpBackend::setResumeOffset(quint64 offset)
       
  1176 {
       
  1177     resumeOffset = offset;
       
  1178 }
       
  1179 
  1096 QT_END_NAMESPACE
  1180 QT_END_NAMESPACE
  1097 
  1181 
  1098 #endif // QT_NO_HTTP
  1182 #endif // QT_NO_HTTP