2

I'm trying to save all outgoing POST data in QtWebKit.

I do it using overriding QNetworkReply *QNetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, QIODevice outgoingData) method and reading an outgoingData that contains outgoing POST data.

The problem is that after reading it, the data become not available in the QIODevice.

How to save an outgoing (PUT, POST) data and keep it available for the future internal Qt operations?

If I need to use another approach to save PUT/POST data - please, let me know.

Code example:

QNetworkReply *MyNetworkAccessManager::createRequest(Operation op, const QNetworkRequest &request, QIODevice *outgoingData)
{     
 QByteArray bArray = outgoingData->readAll();
 // save bArray (that contains POST outgoing data) somewhere
 // do other things, and outgoingData now has no data anymore, as it was already read to bArray 
}

I have tried

QByteArray bArray = outgoingData->readAll();
outgoingData->write(bArray);
qDebug() << bArray;

But in this case I get "QIODevice::write: ReadOnly device" message.

How to save the outgoing POST/PUT data in Qt?

Thanks.

Zelid
  • 6,905
  • 11
  • 52
  • 76

3 Answers3

2

qint64 QIODevice::peek (char * data, qint64 maxSize)

Reads at most maxSize bytes from the device into data, without side effects (i.e., if you call read() after peek(), you will get the same data). Returns the number of bytes read. If an error occurs, such as when attempting to peek a device opened in WriteOnly mode, this function returns -1.

0 is returned when no more data is available for reading.

EDIT

Forget about peak(), it's not good in this situation. You could use it but you would have to do much work to accomplish what you ask for. Instead read Tee is for Tubes, grab code from there and use it.

Link by courtesy of peppe from #qt irc channel on http://irc.freenode.net. I'd like to thank peppe and thiago who were so kind to discuss this problem on #qt channel with me.

In case one day you want to steal incoming (as opposed to outgoing) data from QNetworkAccessManager you'll find answer and code in How to read data from QNetworkReply being used by QWebPage? question.

Community
  • 1
  • 1
Piotr Dobrogost
  • 41,292
  • 40
  • 236
  • 366
  • Looks like a right solution, I do outgoingData->peek(100000); I tried to get the maxSize using outgoingData->size() but it always returns 0. How to get the exact maxSize for the data? Or a random big number is fine? – Zelid Mar 28 '11 at 08:43
  • 1
    @izyda I'm not sure what I meant when I wrote this but thinking about this now problems seem to be a) when to `peek` as at any time data could be read by QtWebKit (referred to as *internal Qt operations* in the question) and b) how to keep track of what was peeked or in other words how to keep sync between peeked data and data read from and still present in the `QIODevice`. Basically to do it right you would have to create something very similar to the `Grantlee::Tee` mentioned in the edit to my answer. – Piotr Dobrogost Aug 26 '15 at 07:33
  • Right - so given that I'm most interested in reading incoming data, I'm probably better off subclassing QNetworkReply and reading the data from there before QWebPage gets it... – alexizydorczyk Aug 27 '15 at 00:11
1

Using pos() and seek() does actually not work in that special case. The idea of using peek() instead seems to be much better. But an example would be helpful. So, here an example of how to get data buffer from given QIODevice's outgoing data in function createRequest() without affecting original data.

if (outgoing != NULL)
{
    const qint64 delta = 100;

    qint64 length = delta;
    QByteArray array;

    while (true)
    {
        char *buffer = new char[length];
        qint64 count = outgoing->peek(buffer, length);

        if (count < length)
        {
            array = QByteArray(buffer, count);
            delete buffer;
            break;
        }

        length += delta;
        delete buffer;
    }
}

For an optimization you may adjust the value of 'delta'.

Axel
  • 11
  • 1
0

Save the IO device marker with QIODevice::pos(). Read data from it. Then restore the marker with QIODevice::seek().

This will only work if the device is a random access one. But I think it covers most of them.

Stephen Chu
  • 12,724
  • 1
  • 35
  • 46