QxtHttpSessionManager: handle broken connections better
This commit is contained in:
parent
4b393e7318
commit
696423b689
|
@ -562,81 +562,85 @@ void QxtHttpSessionManager::processEvents()
|
||||||
if (content) content->ignoreRemainingContent();
|
if (content) content->ignoreRemainingContent();
|
||||||
QHash<QPair<int,int>,QxtWebRequestEvent*>::iterator iPending =
|
QHash<QPair<int,int>,QxtWebRequestEvent*>::iterator iPending =
|
||||||
qxt_d().pendingRequests.find(QPair<int,int>(sessionID, requestID));
|
qxt_d().pendingRequests.find(QPair<int,int>(sessionID, requestID));
|
||||||
if(iPending != qxt_d().pendingRequests.end()){
|
if(iPending != qxt_d().pendingRequests.end()) {
|
||||||
delete *iPending;
|
delete *iPending;
|
||||||
qxt_d().pendingRequests.erase(iPending);
|
qxt_d().pendingRequests.erase(iPending);
|
||||||
}
|
}
|
||||||
|
|
||||||
QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[connector()->getRequestConnection(requestID)];
|
// If no device is returned, the request was aborted before the request body was ready.
|
||||||
QIODevice* source;
|
if(device)
|
||||||
header.setStatusLine(pe->status, pe->statusMessage, state.httpMajorVersion, state.httpMinorVersion);
|
|
||||||
|
|
||||||
if (re)
|
|
||||||
{
|
{
|
||||||
header.setValue("location", re->destination);
|
QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[connector()->getRequestConnection(requestID)];
|
||||||
}
|
QIODevice* source;
|
||||||
|
header.setStatusLine(pe->status, pe->statusMessage, state.httpMajorVersion, state.httpMinorVersion);
|
||||||
|
|
||||||
// Set custom header values
|
if (re)
|
||||||
for (QMultiHash<QString, QString>::iterator it = pe->headers.begin(); it != pe->headers.end(); ++it)
|
|
||||||
{
|
|
||||||
header.setValue(it.key(), it.value());
|
|
||||||
}
|
|
||||||
|
|
||||||
header.setContentType(pe->contentType);
|
|
||||||
if (state.httpMajorVersion == 0 || (state.httpMajorVersion == 1 && state.httpMinorVersion == 0))
|
|
||||||
pe->chunked = false;
|
|
||||||
|
|
||||||
source = pe->dataSource;
|
|
||||||
state.finishedTransfer = false;
|
|
||||||
bool emptyContent = !source->bytesAvailable() && !pe->streaming;
|
|
||||||
state.readyRead = source->bytesAvailable();
|
|
||||||
state.streaming = pe->streaming;
|
|
||||||
|
|
||||||
if (emptyContent)
|
|
||||||
{
|
|
||||||
header.setValue("connection", "close");
|
|
||||||
connector()->writeHeaders(device, header);
|
|
||||||
closeConnection(requestID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pe->dataSource = 0; // so that it isn't destroyed when the event is deleted
|
|
||||||
state.clearHandlers(); // disconnect old handlers
|
|
||||||
|
|
||||||
if (!pe->chunked)
|
|
||||||
{
|
{
|
||||||
state.keepAlive = false;
|
header.setValue("location", re->destination);
|
||||||
state.onBytesWritten = QxtMetaObject::bind(this, SLOT(sendNextBlock(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
|
||||||
state.onReadyRead = QxtMetaObject::bind(this, SLOT(blockReadyRead(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
|
||||||
state.onAboutToClose = QxtMetaObject::bind(this, SLOT(closeConnection(int)), Q_ARG(int, requestID));
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
header.setValue("transfer-encoding", "chunked");
|
|
||||||
state.onBytesWritten = QxtMetaObject::bind(this, SLOT(sendNextChunk(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
|
||||||
state.onReadyRead = QxtMetaObject::bind(this, SLOT(chunkReadyRead(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
|
||||||
state.onAboutToClose = QxtMetaObject::bind(this, SLOT(sendEmptyChunk(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
|
||||||
}
|
|
||||||
QxtMetaObject::connect(device, SIGNAL(bytesWritten(qint64)), state.onBytesWritten, Qt::QueuedConnection);
|
|
||||||
QxtMetaObject::connect(source, SIGNAL(readyRead()), state.onReadyRead, Qt::QueuedConnection);
|
|
||||||
QxtMetaObject::connect(source, SIGNAL(aboutToClose()), state.onAboutToClose, Qt::QueuedConnection);
|
|
||||||
QObject::connect(device, SIGNAL(destroyed()), source, SLOT(deleteLater()));
|
|
||||||
|
|
||||||
if (state.keepAlive)
|
// Set custom header values
|
||||||
|
for (QMultiHash<QString, QString>::iterator it = pe->headers.begin(); it != pe->headers.end(); ++it)
|
||||||
{
|
{
|
||||||
header.setValue("connection", "keep-alive");
|
header.setValue(it.key(), it.value());
|
||||||
}
|
}
|
||||||
else
|
|
||||||
|
header.setContentType(pe->contentType);
|
||||||
|
if (state.httpMajorVersion == 0 || (state.httpMajorVersion == 1 && state.httpMinorVersion == 0))
|
||||||
|
pe->chunked = false;
|
||||||
|
|
||||||
|
source = pe->dataSource;
|
||||||
|
state.finishedTransfer = false;
|
||||||
|
bool emptyContent = !source->bytesAvailable() && !pe->streaming;
|
||||||
|
state.readyRead = source->bytesAvailable();
|
||||||
|
state.streaming = pe->streaming;
|
||||||
|
|
||||||
|
if (emptyContent)
|
||||||
{
|
{
|
||||||
header.setValue("connection", "close");
|
header.setValue("connection", "close");
|
||||||
|
connector()->writeHeaders(device, header);
|
||||||
|
closeConnection(requestID);
|
||||||
}
|
}
|
||||||
connector()->writeHeaders(device, header);
|
else
|
||||||
if (state.readyRead)
|
|
||||||
{
|
{
|
||||||
if (pe->chunked)
|
pe->dataSource = 0; // so that it isn't destroyed when the event is deleted
|
||||||
sendNextChunk(requestID, source);
|
state.clearHandlers(); // disconnect old handlers
|
||||||
|
|
||||||
|
if (!pe->chunked)
|
||||||
|
{
|
||||||
|
state.keepAlive = false;
|
||||||
|
state.onBytesWritten = QxtMetaObject::bind(this, SLOT(sendNextBlock(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
||||||
|
state.onReadyRead = QxtMetaObject::bind(this, SLOT(blockReadyRead(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
||||||
|
state.onAboutToClose = QxtMetaObject::bind(this, SLOT(closeConnection(int)), Q_ARG(int, requestID));
|
||||||
|
}
|
||||||
else
|
else
|
||||||
sendNextBlock(requestID, source);
|
{
|
||||||
|
header.setValue("transfer-encoding", "chunked");
|
||||||
|
state.onBytesWritten = QxtMetaObject::bind(this, SLOT(sendNextChunk(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
||||||
|
state.onReadyRead = QxtMetaObject::bind(this, SLOT(chunkReadyRead(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
||||||
|
state.onAboutToClose = QxtMetaObject::bind(this, SLOT(sendEmptyChunk(int, QObject*)), Q_ARG(int, requestID), Q_ARG(QObject*, source));
|
||||||
|
}
|
||||||
|
QxtMetaObject::connect(device, SIGNAL(bytesWritten(qint64)), state.onBytesWritten, Qt::QueuedConnection);
|
||||||
|
QxtMetaObject::connect(source, SIGNAL(readyRead()), state.onReadyRead, Qt::QueuedConnection);
|
||||||
|
QxtMetaObject::connect(source, SIGNAL(aboutToClose()), state.onAboutToClose, Qt::QueuedConnection);
|
||||||
|
QObject::connect(device, SIGNAL(destroyed()), source, SLOT(deleteLater()));
|
||||||
|
|
||||||
|
if (state.keepAlive)
|
||||||
|
{
|
||||||
|
header.setValue("connection", "keep-alive");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
header.setValue("connection", "close");
|
||||||
|
}
|
||||||
|
connector()->writeHeaders(device, header);
|
||||||
|
if (state.readyRead)
|
||||||
|
{
|
||||||
|
if (pe->chunked)
|
||||||
|
sendNextChunk(requestID, source);
|
||||||
|
else
|
||||||
|
sendNextBlock(requestID, source);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -723,6 +727,7 @@ void QxtHttpSessionManager::sendEmptyChunk(int requestID, QObject* dataSource)
|
||||||
void QxtHttpSessionManager::closeConnection(int requestID)
|
void QxtHttpSessionManager::closeConnection(int requestID)
|
||||||
{
|
{
|
||||||
QIODevice* device = connector()->getRequestConnection(requestID);
|
QIODevice* device = connector()->getRequestConnection(requestID);
|
||||||
|
if(!device) return;
|
||||||
QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device];
|
QxtHttpSessionManagerPrivate::ConnectionState& state = qxt_d().connectionState[device];
|
||||||
state.finishedTransfer = true;
|
state.finishedTransfer = true;
|
||||||
QTcpSocket* socket = qobject_cast<QTcpSocket*>(device);
|
QTcpSocket* socket = qobject_cast<QTcpSocket*>(device);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user