Skip to content
This repository has been archived by the owner on Dec 21, 2018. It is now read-only.

Commit

Permalink
response body is only available in onResourceReceived event,
Browse files Browse the repository at this point in the history
if url matches one of the patterns in 'page.captureContent' property

ariya#10158
  • Loading branch information
Dmitry Parshin authored and vitallium committed May 31, 2015
1 parent d0fde08 commit 327f91d
Show file tree
Hide file tree
Showing 9 changed files with 132 additions and 8 deletions.
39 changes: 38 additions & 1 deletion src/networkaccessmanager.cpp
Expand Up @@ -254,6 +254,28 @@ QVariantMap NetworkAccessManager::customHeaders() const
return m_customHeaders;
}

QStringList NetworkAccessManager::captureContent() const
{
return m_captureContentPatterns;
}

void NetworkAccessManager::setCaptureContent(const QStringList &patterns)
{
m_captureContentPatterns = patterns;

compileCaptureContentPatterns();
}

void NetworkAccessManager::compileCaptureContentPatterns()
{
for(QStringList::const_iterator it = m_captureContentPatterns.constBegin();
it != m_captureContentPatterns.constEnd(); ++it) {

m_compiledCaptureContentPatterns.append(QRegExp(*it, Qt::CaseInsensitive));
}
}


void NetworkAccessManager::setCookieJar(QNetworkCookieJar *cookieJar)
{
QNetworkAccessManager::setCookieJar(cookieJar);
Expand Down Expand Up @@ -322,7 +344,9 @@ QNetworkReply *NetworkAccessManager::createRequest(Operation op, const QNetworkR
emit resourceRequested(data, &jsNetworkRequest);

QNetworkReply *nested_reply = QNetworkAccessManager::createRequest(op, req, outgoingData);
QNetworkReply *tracked_reply = m_replyTracker.trackReply(nested_reply, m_idCounter);
QNetworkReply *tracked_reply = m_replyTracker.trackReply(nested_reply,
m_idCounter,
shouldCaptureResponse(req.url().toString()));

// reparent jsNetworkRequest to make sure that it will be destroyed with QNetworkReply
jsNetworkRequest.setParent(tracked_reply);
Expand All @@ -343,6 +367,19 @@ QNetworkReply *NetworkAccessManager::createRequest(Operation op, const QNetworkR
return tracked_reply;
}

bool NetworkAccessManager::shouldCaptureResponse(const QString& url)
{
for(QList<QRegExp>::const_iterator it = m_compiledCaptureContentPatterns.constBegin();
it != m_compiledCaptureContentPatterns.constEnd(); ++it) {

if(-1 != it->indexIn(url)) {
return true;
}
}

return false;
}

void NetworkAccessManager::handleTimeout()
{
TimeoutTimer *nt = qobject_cast<TimeoutTimer*>(sender());
Expand Down
9 changes: 9 additions & 0 deletions src/networkaccessmanager.h
Expand Up @@ -36,6 +36,7 @@
#include <QNetworkReply>
#include <QSslConfiguration>
#include <QTimer>
#include <QStringList>

#include "networkreplytracker.h"

Expand Down Expand Up @@ -90,6 +91,8 @@ class NetworkAccessManager : public QNetworkAccessManager
void setResourceTimeout(int resourceTimeout);
void setCustomHeaders(const QVariantMap &headers);
QVariantMap customHeaders() const;
QStringList captureContent() const;
void setCaptureContent(const QStringList &patterns);

void setCookieJar(QNetworkCookieJar *cookieJar);

Expand Down Expand Up @@ -118,9 +121,15 @@ private slots:
void handleTimeout();

private:

bool shouldCaptureResponse(const QString& url);
void compileCaptureContentPatterns();

int m_idCounter;
QNetworkDiskCache* m_networkDiskCache;
QVariantMap m_customHeaders;
QStringList m_captureContentPatterns;
QList<QRegExp> m_compiledCaptureContentPatterns;
QSslConfiguration m_sslConfiguration;

NetworkReplyTracker m_replyTracker;
Expand Down
10 changes: 7 additions & 3 deletions src/networkreplyproxy.cpp
Expand Up @@ -32,9 +32,11 @@

#include "networkreplyproxy.h"

NetworkReplyProxy::NetworkReplyProxy(QObject* parent, QNetworkReply* reply)
NetworkReplyProxy::NetworkReplyProxy(QObject* parent, QNetworkReply* reply,
bool shouldCaptureResponse)
: QNetworkReply(parent)
, m_reply(reply)
, m_shouldCaptureResponseBody(shouldCaptureResponse)
{
// apply attributes...
setOperation(m_reply->operation());
Expand Down Expand Up @@ -154,8 +156,10 @@ void NetworkReplyProxy::readInternal()
{
QByteArray data = m_reply->readAll();

//this is a response buffer, whole response is stored here
m_data += data;
if(m_shouldCaptureResponseBody) {
//this is a response buffer, whole response is stored here
m_data += data;
}

//this is a temporary buffer, data is wiped after a call to 'readData'
m_buffer += data;
Expand Down
6 changes: 5 additions & 1 deletion src/networkreplyproxy.h
Expand Up @@ -43,8 +43,11 @@ class NetworkReplyProxy : public QNetworkReply {

/*
reply - reply to be proxied(nested reply)
shouldCaptureResponseBody - if true, response body will be collected and
available through body() method
*/
NetworkReplyProxy(QObject* parent, QNetworkReply* reply);
NetworkReplyProxy(QObject* parent, QNetworkReply* reply,
bool shouldCaptureResponseBody);


/*
Expand Down Expand Up @@ -88,6 +91,7 @@ public Q_SLOTS:
QNetworkReply* m_reply;
QByteArray m_data;
QByteArray m_buffer;
bool m_shouldCaptureResponseBody;
};

#endif // NETWORKREPLYPROXY_H
5 changes: 3 additions & 2 deletions src/networkreplytracker.cpp
Expand Up @@ -37,9 +37,10 @@ NetworkReplyTracker::NetworkReplyTracker(QObject* parent)
}


QNetworkReply* NetworkReplyTracker::trackReply(QNetworkReply *reply, int requestId)
QNetworkReply* NetworkReplyTracker::trackReply(QNetworkReply *reply, int requestId,
bool shouldCaptureResponseBody)
{
NetworkReplyProxy *proxy = new NetworkReplyProxy(this, reply);
NetworkReplyProxy *proxy = new NetworkReplyProxy(this, reply, shouldCaptureResponseBody);

/*
Tracking link between proxy and proxied reply.
Expand Down
4 changes: 3 additions & 1 deletion src/networkreplytracker.h
Expand Up @@ -54,8 +54,10 @@ class NetworkReplyTracker: public QObject {
/*
reply - reply to track
requestId - unique request id, used to distinguis replies internally
shouldCaptureResponseBody - if true, response body will be available in 'finished' signal
*/
QNetworkReply* trackReply(QNetworkReply *reply, int requestId);
QNetworkReply* trackReply(QNetworkReply *reply, int requestId,
bool shouldCaptureResponseBody);


/*
Expand Down
10 changes: 10 additions & 0 deletions src/webpage.cpp
Expand Up @@ -775,6 +775,16 @@ QVariantMap WebPage::customHeaders() const
return m_networkAccessManager->customHeaders();
}

QStringList WebPage::captureContent() const
{
return m_networkAccessManager->captureContent();
}

void WebPage::setCaptureContent(const QStringList &patterns)
{
m_networkAccessManager->setCaptureContent(patterns);
}

void WebPage::setCookieJar(CookieJar *cookieJar) {
m_cookieJar = cookieJar;
m_customWebPage->setCookieJar(m_cookieJar);
Expand Down
20 changes: 20 additions & 0 deletions src/webpage.h
Expand Up @@ -81,6 +81,7 @@ class WebPage : public QObject, public QWebFrame::PrintCallback
Q_PROPERTY(QString focusedFrameName READ focusedFrameName)
Q_PROPERTY(QObject *cookieJar READ cookieJar WRITE setCookieJarFromQObject)
Q_PROPERTY(QVariantList cookies READ cookies WRITE setCookies)
Q_PROPERTY(QStringList captureContent READ captureContent WRITE setCaptureContent)

public:
WebPage(QObject *parent, const QUrl &baseUrl = QUrl());
Expand Down Expand Up @@ -184,6 +185,25 @@ class WebPage : public QObject, public QWebFrame::PrintCallback
* Pages that this page has currently open.
*/
QStringList pagesWindowName() const;
/**
* Returns a list of URL patterns, for which response body
* will be captured and returned in onResourceReceived event
*
* @brief captureContent
* @return List (JS Array) containing currently set patterns
*/
QStringList captureContent() const;

/**
* Allows to set a list of URL patterns, for which response body
* will be captured and returned in onResourceReceived event
*
* EXAMPLE: page.captureContent = ['/foo/', '\.jpg' ]
*
* @brief captureContent
* @param patterns Expects a QList of QString
*/
void setCaptureContent(const QStringList &patterns);

/**
* Returns "true" if it owns the pages it creates (and keeps them in "pages[]").
Expand Down
37 changes: 37 additions & 0 deletions test/webpage-spec.js
Expand Up @@ -182,6 +182,8 @@ describe("WebPage object", function() {

it("should contain resource body when last chunk of resource received", function() {
var page = require('webpage').create();
page.captureContent = ['/foo'];

var server = require('webserver').create();
server.listen(12345, function(request, response) {
response.statusCode = 200;
Expand Down Expand Up @@ -212,6 +214,41 @@ describe("WebPage object", function() {

});


it("should not contain resource body if not in the captureContent list", function() {
var page = require('webpage').create();
page.captureContent = ['/foo'];
var server = require('webserver').create();
server.listen(12345, function(request, response) {
response.statusCode = 200;
response.write('resource body');
response.close();
});

var url = "http://localhost:12345/some/other/url";
var lastChunk = "";
var bodySize = 0;
runs(function() {
page.onResourceReceived = function(resource) {
lastChunk = resource.body;
bodySize = resource.bodySize;
};
page.open(url, function(status) {
});
});

waits(50);

runs(function() {
expect(lastChunk).toEqual('');
expect(0).toEqual(lastChunk.length);
page.onResourceReceived = null;
server.close();
});

});


it("should set valid cookie properly, then remove it", function() {
var server = require('webserver').create();
server.listen(12345, function(request, response) {
Expand Down

0 comments on commit 327f91d

Please sign in to comment.