diff --git a/src/qhttpsocket.cpp b/src/qhttpsocket.cpp index 1d3abf8..927d236 100644 --- a/src/qhttpsocket.cpp +++ b/src/qhttpsocket.cpp @@ -59,6 +59,7 @@ QByteArray QHttpSocketPrivate::statusReason(int statusCode) const case QHttpSocket::OK: return "OK"; case QHttpSocket::MovedPermanently: return "MOVED PERMANENTLY"; case QHttpSocket::Found: return "FOUND"; + case QHttpSocket::BadRequest: return "BAD REQUEST"; case QHttpSocket::Forbidden: return "FORBIDDEN"; case QHttpSocket::NotFound: return "NOT FOUND"; case QHttpSocket::InternalServerError: return "INTERNAL SERVER ERROR"; @@ -71,6 +72,7 @@ void QHttpSocketPrivate::onReadyRead() // Append all of the new data to the read buffer readBuffer.append(socket->readAll()); + // If reading headers, return if they could not be read (yet) if(readState == ReadHeaders) { if(!readHeaders()) { return; @@ -80,6 +82,8 @@ void QHttpSocketPrivate::onReadyRead() if(readState == ReadData) { readData(); } else if(readState == ReadFinished) { + + // Any data received here is unexpected and should be ignored readBuffer.clear(); } } @@ -113,10 +117,13 @@ bool QHttpSocketPrivate::readHeaders() // Attempt to parse the headers and if a problem is encountered, abort // the connection (so that no more data is read or written) and return if(!QHttpParser::parseRequestHeaders(readBuffer.left(index), requestMethod, requestPath, requestHeaders)) { - socket->abort(); + q->writeError(QHttpSocket::BadRequest); return false; } + // Indicate that the headers have been parsed + Q_EMIT q->headersParsed(); + // Remove the headers from the buffer readBuffer.remove(0, index + 4); @@ -131,9 +138,6 @@ bool QHttpSocketPrivate::readHeaders() Q_EMIT q->readChannelFinished(); } - // Indicate that the headers have been parsed - Q_EMIT q->headersParsed(); - return true; } diff --git a/src/qhttpsocket.h b/src/qhttpsocket.h index 76d01df..0ce5213 100644 --- a/src/qhttpsocket.h +++ b/src/qhttpsocket.h @@ -94,6 +94,8 @@ public: MovedPermanently = 301, /// Resource is available at an alternate URI Found = 302, + /// Bad client request + BadRequest = 400, /// Access to the resource is forbidden Forbidden = 403, /// Resource was not found diff --git a/src/qiodevicecopier.cpp b/src/qiodevicecopier.cpp index f579974..74429ed 100644 --- a/src/qiodevicecopier.cpp +++ b/src/qiodevicecopier.cpp @@ -92,11 +92,6 @@ QIODeviceCopier::QIODeviceCopier(QIODevice *src, QIODevice *dest, QObject *paren { } -qint64 QIODeviceCopier::bufferSize() const -{ - return d->bufferSize; -} - void QIODeviceCopier::setBufferSize(qint64 size) { d->bufferSize = size; diff --git a/src/qiodevicecopier.h b/src/qiodevicecopier.h index 7992e1d..70f89ed 100644 --- a/src/qiodevicecopier.h +++ b/src/qiodevicecopier.h @@ -36,12 +36,33 @@ class QHTTPENGINE_EXPORT QIODeviceCopierPrivate; * * QIODeviceCopier provides a set of methods for reading data from a QIODevice * and writing it to another. The class operates asynchronously and therefore - * can be used from the main thread. + * can be used from the main thread. The copier is initialized with pointers + * to two QIODevices: + * + * @code + * QFile srcFile("src.txt"); + * QFile destFile("dest.txt"); + * + * QIODeviceCopier copier(&srcFile, &destFile); + * copier.start() + * @endcode + * + * Notice in the example above that it is not necessary to open the devices + * prior to starting the copy operation. The copier will attempt to open both + * devices with the appropriate mode if they are not already open. + * + * If the source device is sequential, data will be read as it becomes + * available and immediately written to the destination device. If the source + * device is not sequential, data will be read and written in blocks. The size + * of the blocks can be modified with the setBufferSize() method. + * + * If an error occurs, the error() signal will be emitted. When the copy + * completes, either by reading all of the data from the source device or + * encountering an error, the finished() signal is emitted. */ class QHTTPENGINE_EXPORT QIODeviceCopier : public QObject { Q_OBJECT - Q_PROPERTY(qint64 bufferSize READ bufferSize WRITE setBufferSize) public: @@ -50,11 +71,6 @@ public: */ QIODeviceCopier(QIODevice *src, QIODevice *dest, QObject *parent = 0); - /** - * @brief Retrieve the current buffer size - */ - qint64 bufferSize() const; - /** * @brief Set the size of the buffer */ diff --git a/tests/TestQHttpParser.cpp b/tests/TestQHttpParser.cpp index ac81997..47700f3 100644 --- a/tests/TestQHttpParser.cpp +++ b/tests/TestQHttpParser.cpp @@ -31,13 +31,13 @@ typedef QList QByteArrayList; Q_DECLARE_METATYPE(QHttpHeaderMap) -const QByteArray Line1 = "a: b"; const QIByteArray Key1 = "a"; const QByteArray Value1 = "b"; +const QByteArray Line1 = Key1 + ": " + Value1; -const QByteArray Line2 = "c: d"; const QIByteArray Key2 = "c"; const QByteArray Value2 = "d"; +const QByteArray Line2 = Key2 + ": " + Value2; class TestQHttpParser : public QObject { diff --git a/tests/TestQHttpSocket.cpp b/tests/TestQHttpSocket.cpp index f3c87b9..3733a2d 100644 --- a/tests/TestQHttpSocket.cpp +++ b/tests/TestQHttpSocket.cpp @@ -20,7 +20,6 @@ * IN THE SOFTWARE. */ -#include #include #include #include @@ -112,10 +111,13 @@ void TestQHttpSocket::testRedirect() { CREATE_SOCKET_PAIR(); + QSignalSpy disconnectedSpy(pair.client(), SIGNAL(disconnected())); + server.writeRedirect(Path, true); QTRY_COMPARE(client.statusCode(), static_cast(QHttpSocket::MovedPermanently)); QCOMPARE(client.headers().value("Location"), Path); + QTRY_COMPARE(disconnectedSpy.count(), 1); } void TestQHttpSocket::testSignals() diff --git a/tests/TestQIODeviceCopier.cpp b/tests/TestQIODeviceCopier.cpp index 9bbe8e9..bcd12a0 100644 --- a/tests/TestQIODeviceCopier.cpp +++ b/tests/TestQIODeviceCopier.cpp @@ -81,7 +81,7 @@ void TestQIODeviceCopier::testQTcpSocket() copier.start(); pair.client()->write(SampleData); - pair.client()->disconnectFromHost(); + pair.client()->close(); QTRY_COMPARE(finishedSpy.count(), 1); QCOMPARE(errorSpy.count(), 0);