How to intercept AJAX requests in QtWebKit?

I want to intercept, check and (if necessary) reject AJAX requests based on the fingerprint of the SSL certificate. I am using the QNetworkAccessManager::createRequest(...) function to issue requests. Everything works fine when I use QWebFrame::load(...) . Even content uploaded to the request (for example, .css or .js files) emits signals. Unfortunately, none of the AJAX requests generate any signals. I know that Signals are connected to the same slots (for "normal" as well as AJAX requests) in the MyNetworkAccessManager::createRequest(...) function.

 QNetworkReply *reply = QNetworkAccessManager::createRequest(op, req, outgoingData); connect(reply, SIGNAL(readyRead()), this, SLOT(handleStarted())); connect(reply, SIGNAL(sslErrors(const QList<QSslError> &)), this, SLOT(handleSslErrors(const QList<QSslError> &))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleNetworkError())); 

Why are AJAX requests so different? Where can I access them?

+6
source share
1 answer

From what I can tell, AJAX requests emit a ready signal in the QNetworkAccessManager. You need to connect to the QNetworkAccessManager instance in your QWebPage instance:

 QWebPage *page = ui->webView->page(); QNetworkAccessManager *nam = page->networkAccessManager(); connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*))); QFile file; file.setFileName(":/js/jquery-2.1.1.min.js"); // jQuery is loaded as a resource file.open(QIODevice::ReadOnly); QString jQuery = file.readAll(); file.close(); ui->webView->load(QUrl("about:blank")); QWebFrame *frame = m_page->mainFrame(); frame->evaluateJavaScript(jQuery); // load jQuery // check that jQuery is loaded frame->evaluateJavaScript("$(document).ready(function() { alert('jQuery loaded!'); });"); // do an AJAX GET frame->evaluateJavaScript("$.ajax({" "url: 'http://www.json-generator.com/api/json/get/cqkXBAEoQy?indent=2'," "method: 'GET'," "dataType: 'json'" "}).done(function (data) {" "for (var i = 0; i < data.length; i++) {" "alert(data[i].name);" "}" "}).error(function (data) { alert('AJAX error'); });"); 

Then you can track the responses in the replyFinished slot like this:

 void MainWindow::replyFinished(QNetworkReply *reply) { QByteArray bytes = reply->readAll(); QString str = QString::fromUtf8(bytes.data(), bytes.size()); QString replyUrl = reply->url().toString(); int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); qDebug() << statusCode; qDebug() << replyUrl; qDebug() << str; } 

I noticed that the jQuery AJAX promise does not seem to be fulfilled when you do something with QNetworkReply, but you can see that the request really ends in the debug console.

See my GitHub repository to try out the code above: https://github.com/pcmantinker/QtWebkitAJAX

As for blocking connections based on SSL certificates, you will have to subclass QNetworkAccessManager and override QNetworkAccessManager :: createRequest. Something like this might work:

 QNetworkReply *CustomQNetworkAccessManager::createRequest(Operation op, const QNetworkRequest& request, QIODevice* outgoingData) { QNetworkRequest req(request); QNetworkReply *reply = QNetworkAccessManager::createRequest(op, req, outgoingData); QSslConfiguration *sslConfig = reply->sslConfiguration(); QList<QSslCertificate> sslCaCerts = sslConfig->caCertificates(); // do something with sslCaCerts return reply; } 
+2
source

Source: https://habr.com/ru/post/970711/


All Articles