How do I make my own custom QNetworkReply?
-
I've been trying to create my own custom QNetworkReply class which return custom bytes from reply. I do return that class from my QNetworkAccessManager::createRequest() overload that I also did overload. My problem is, none of my function overloads are called and consequently the QWebView's request fail, as the reply is "corrupted". I've tried to take some inspiration from Qt tests lib's FakeReply but I fail to make mine work.
Here's my code:fakereply.h
class FakeReply : public QNetworkReply { Q_OBJECT public: FakeReply(const QNetworkRequest& request, QByteArray &data, QObject* parent = 0); ~FakeReply(); QByteArray readAll(); QByteArray read(qint64 maxSize); qint64 peek(char *buffer, qint64 maxlen); QByteArray peek(qint64 maxLen); qint64 size() const; virtual qint64 bytesAvailable() const; bool isFinished() const; virtual void abort(); virtual void close(); bool isSequential() const; protected: qint64 readData(char*, qint64) override; private: QByteArray data; };
fakereply.cpp
FakeReply::FakeReply(const QNetworkRequest &request, QByteArray &bytes, QObject *parent) : QNetworkReply(parent), data(bytes) { setOperation(QNetworkAccessManager::GetOperation); setRequest(request); setUrl(request.url()); open(QIODevice::ReadOnly); setFinished(true); emit finished(); }
the class is used like this:
QNetworkReply *MyNetworkAccessManager::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &request, QIODevice *outgoingData) { QString path = request.url().path(); QNetworkReply *reply = QNetworkAccessManager::createRequest(op, request, outgoingData); if(path == QStringLiteral("/testing")) { QByteArray response = waitThenReadAll(reply); return new FakeReply(request, response); } return reply; } FakeReply::~FakeReply() { close(); } QByteArray FakeReply::readAll() { qDebug() << "FakeReply::readAll() got called!"; size_t len = data.length(); const char *bytes = static_cast<const char*>(data.data()); char *buffer = static_cast<char*>(malloc(len)); ASSERT(buffer != NULL, "run out of memory"); memcpy(buffer, bytes, len); QByteArray output; output.setRawData(buffer, len); data = data.remove(0, len); return output; } QByteArray FakeReply::read(qint64 maxSize) { qDebug() << "QByteArray FakeReply::read() got called!"; static char* buffer = nullptr; if(bytesAvailable() == 0) { return QByteArray(); } size_t len = computeMaxNumberOfBytes(maxSize); if(buffer != nullptr) { free(buffer); } buffer = static_cast<char*>(malloc(len)); ASSERT(buffer != NULL, "run out of memory"); memcpy(buffer, data.data(), len); data = data.remove(0, len); QByteArray output; output.setRawData(buffer, len); return output; } qint64 FakeReply::peek(char *buffer, qint64 maxlen) { qDebug() << "FakeReply::peek() got called!"; size_t len = computeMaxNumberOfBytes(maxlen); memcpy(buffer, data.data(), len); return static_cast<qint64>(len); } QByteArray FakeReply::peek(qint64 maxlen) { qDebug() << "FakeReply::peek(qint64 maxlen) got called!"; QByteArray output; output.setRawData(data.data(), computeMaxNumberOfBytes(maxlen)); return output; } qint64 FakeReply::size() const { return data.length(); } qint64 FakeReply::bytesAvailable() const { qDebug() << "FakeReply::bytesAvailable()"; return data.length(); } bool FakeReply::isFinished() const { qDebug() << "FakeReply::isFinished() got called!"; return true; } void FakeReply::abort() { qDebug() << "FakeReply::abort() got called!"; } void FakeReply::close() { qDebug() << "FakeReply::close() got called!"; } bool FakeReply::isSequential() const { qDebug() << "FakeReply::isSequential() const got called!"; return false; } qint64 FakeReply::readData(char *, qint64) { qDebug() << "FakeReply::readData() got called!"; return 0; }
-
Hi
It really looks like this sample
https://github.com/richmoore/qt-examples/tree/master/qcustomnetworkreplyNothing jumped to eye with your code.
-
Thank you so much for that code samples! I've been trying to make it work for days. I've tried override/reimplement nearly every method from QNetworkReply and couldn't figure out why my methods weren't being called. My issue was rather simple. I was using emit finished() but then I noticied that your sampel was using:
```
QTimer::singleShot(0, this, SIGNAL(readyRead()));
QTimer::singleShot(0, this, SIGNAL(finished()));So I give try and it worked!
-
Super :)
It was a long shot but sometimes one is lucky :)