void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *data) { Q_Q(QNetworkReplyImpl); outgoingData = data; request = req; url = request.url(); operation = op; if (outgoingData && backend) { // there is data to be uploaded, e.g. HTTP POST. if (!backend->needsResetableUploadData() || !outgoingData->isSequential()) { // backend does not need upload buffering or // fixed size non-sequential // just start the operation QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } else { bool bufferingDisallowed = req.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute, false).toBool(); if (bufferingDisallowed) { // if a valid content-length header for the request was supplied, we can disable buffering // if not, we will buffer anyway if (req.header(QNetworkRequest::ContentLengthHeader).isValid()) { QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } else { state = Buffering; QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection); } } else { // _q_startOperation will be called when the buffering has finished. state = Buffering; QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection); } } } else { // No outgoing data (e.g. HTTP GET request) // or no backend // if no backend, _q_startOperation will handle the error of this // for HTTP, we want to send out the request as fast as possible to the network, without // invoking methods in a QueuedConnection #ifndef QT_NO_HTTP if (qobject_cast<QNetworkAccessHttpBackend *>(backend)) { _q_startOperation(); } else { QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } #else QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); #endif // QT_NO_HTTP } q->QIODevice::open(QIODevice::ReadOnly); }
/* Migrates the backend of the QNetworkReply to a new network connection if required. Returns true if the reply is migrated or it is not required; otherwise returns false. */ bool QNetworkReplyImplPrivate::migrateBackend() { Q_Q(QNetworkReplyImpl); // Network reply is already finished or aborted, don't need to migrate. if (state == Finished || state == Aborted) return true; // Backend does not support resuming download. if (!backend->canResume()) return false; // Request has outgoing data, not migrating. if (outgoingData) return false; // Request is serviced from the cache, don't need to migrate. if (copyDevice) return true; state = QNetworkReplyImplPrivate::Reconnecting; if (backend) { delete backend; backend = 0; } cookedHeaders.clear(); rawHeaders.clear(); preMigrationDownloaded = bytesDownloaded; backend = manager->d_func()->findBackend(operation, request); if (backend) { backend->setParent(q); backend->reply = this; backend->setResumeOffset(bytesDownloaded); } #ifndef QT_NO_HTTP if (qobject_cast<QNetworkAccessHttpBackend *>(backend)) { _q_startOperation(); } else { QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } #else QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); #endif // QT_NO_HTTP return true; }
void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *data) { Q_Q(QNetworkReplyImpl); outgoingData = data; request = req; url = request.url(); operation = op; q->QIODevice::open(QIODevice::ReadOnly); // Internal code that does a HTTP reply for the synchronous Ajax // in QtWebKit. QVariant synchronousHttpAttribute = req.attribute( static_cast<QNetworkRequest::Attribute>(QNetworkRequest::SynchronousRequestAttribute)); // The synchronous HTTP is a corner case, we will put all upload data in one big QByteArray in the outgoingDataBuffer. // Yes, this is not the most efficient thing to do, but on the other hand synchronous XHR needs to die anyway. if (synchronousHttpAttribute.toBool() && outgoingData) { outgoingDataBuffer = QSharedPointer<QRingBuffer>(new QRingBuffer()); qint64 previousDataSize = 0; do { previousDataSize = outgoingDataBuffer->size(); outgoingDataBuffer->append(outgoingData->readAll()); } while (outgoingDataBuffer->size() != previousDataSize); } if (backend) backend->setSynchronous(synchronousHttpAttribute.toBool()); if (outgoingData && backend && !backend->isSynchronous()) { // there is data to be uploaded, e.g. HTTP POST. if (!backend->needsResetableUploadData() || !outgoingData->isSequential()) { // backend does not need upload buffering or // fixed size non-sequential // just start the operation QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } else { bool bufferingDisallowed = req.attribute(QNetworkRequest::DoNotBufferUploadDataAttribute, false).toBool(); if (bufferingDisallowed) { // if a valid content-length header for the request was supplied, we can disable buffering // if not, we will buffer anyway if (req.header(QNetworkRequest::ContentLengthHeader).isValid()) { QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } else { state = Buffering; QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection); } } else { // _q_startOperation will be called when the buffering has finished. state = Buffering; QMetaObject::invokeMethod(q, "_q_bufferOutgoingData", Qt::QueuedConnection); } } } else { // for HTTP, we want to send out the request as fast as possible to the network, without // invoking methods in a QueuedConnection #ifndef QT_NO_HTTP if (backend && backend->isSynchronous()) { _q_startOperation(); } else { QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); } #else if (backend && backend->isSynchronous()) _q_startOperation(); else QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection); #endif // QT_NO_HTTP } }