Как мне создать свой собственный QNetworkReply?

Я пытался создать свой собственный класс QNetworkReply, который возвращает пользовательские байты из ответа. Я возвращаю этот класс из моей перегрузки QNetworkAccessManager::createRequest(), которую я также перегрузил. Моя проблема в том, что ни одна из моих перегрузок функций не вызывается, и, следовательно, запрос QWebView не выполняется, поскольку ответ «поврежден». Я пытался черпать вдохновение из библиотеки тестов Qt FakeReply, но у меня не получается.

Вот мой код:

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;
};

И файл .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();
}

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;
}

класс используется так:

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;
   }

person Jack    schedule 01.02.2018    source источник
comment
Значит, ваш метод MyNetworkAccessManager::createRequest() не вызывается? Не могли бы вы опубликовать файл *.h для вашего менеджера доступа?   -  person Dariusz Scharsig    schedule 02.02.2018
comment
Мой MyNetworkAccessManager::createRequest() вызывается, а не все методы из моего FakeReply, возвращаемые MyNetworkAccessManager::createRequest().   -  person Jack    schedule 02.02.2018


Ответы (1)


Для тех, у кого такая же проблема, я получил ответ с примером кода из here: Чего мне не хватало в моем коде, так это того, что я использовал emit finish(), а не

QTimer::singleShot(0, this, SIGNAL(readyRead()));
QTimer::singleShot(0, this, SIGNAL(finished()));

Это сработало.

person Jack    schedule 03.02.2018
comment
Хорошо, я вижу проблему. Вы заставили его работать. Это хорошо. Ваша проблема заключалась в том, что вы вызвали emit finished() в конструкторе. Сигналы там не работают, так как объект еще не существует (т.е. вызов new FakeReply(...) еще не вернулся), поэтому с ним ничего не связано. Но это хорошая работа вокруг. - person Dariusz Scharsig; 03.02.2018