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 |