Details
-
Bug
-
Resolution: Fixed
-
P1: Critical
-
5.15.0
-
None
-
Qt for Webassembly 5.15.0, emscripten 1.39.11 on Windows 10
-
-
ce8c33e710a9003a1912ab09fc31417b50b7a4b5 (qt/qtbase/dev) 36c80ec4076fcbc44c8c27de5c3b11398be39152 (qt/qtbase/5.15)
Description
QNetworkAccessManager HTTP POST requests are not working as intended in webassembly.
The form data appears to be missing, and is replaced with the POST URL in Unicode format. However the length is set to the length of the argument in the ->post() call.
The form data sent in the example provided is:
All your base are belong to us 1234456789012345678901234567890123456789012345678901234567890
And the reply from a simple echo service on the host with the raw data in hex and as a string is:
Post length: 92 Hex: 68007400740070003a002f002f0073006e006100760065006e006700650072002e0063006f006d002f007700610073006d006e006500740074006500730074002e007000680070000000610073006d006e0065007400740065007300 Text: h
The post length is correct. Converting the unicode hex returned as text is:
http://snavenger.com/wasmnettest.phpasmnettes
So the form data is actually the post URL. Note if the length of the form data is longer than the post URL (the numerical padding test), it appears to overrun the string.
A second issue - this example only runs if you do not set the content type header. On Windows, this results in a debug warning, but the default works fine:
content-type missing in HTTP POST, defaulting to application/x-www-form-urlencoded. Use QNetworkRequest::setHeader() to fix this problem.
However, actually attempting to set the header on the request crashes in Webassembly with the following error:
Application exit (RuntimeError: memory access out of bounds) [Chrome]
Application exit (RuntimeError: Memory index is out of range) [Edge]
The following minimal example works as expected on Windows and MacOS.
main.cpp:
#include "mainwindow.h" #include <QApplication> #include <QNetworkAccessManager> int main(int argc, char *argv[]) { QApplication a(argc, argv); MainWindow w; QNetworkAccessManager *qnam = new QNetworkAccessManager(); w.connect(qnam, &QNetworkAccessManager::finished, &w, &MainWindow::netReply); QNetworkRequest req; req.setUrl(QUrl("http://snavenger.com/wasmnettest.php")); // Setting header doesn't work in webassem // req.setHeader(QNetworkRequest::KnownHeaders::ContentTypeHeader, "application/x-www-form-urlencoded"); qnam->post(req, QByteArray("All your base are belong to us 1234456789012345678901234567890123456789012345678901234567890")); w.show(); return a.exec(); }
mainwindow.h:
#include <QMainWindow> #include <QNetworkAccessManager> #include <QNetworkReply> class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr); ~MainWindow(); void netReply(QNetworkReply *); };
mainwindow.cpp:
#include "mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
{
}
MainWindow::~MainWindow()
{
}
void MainWindow::netReply(QNetworkReply *reply)
{
QString resp = reply->readAll();
qDebug() << resp;
}
PHP echo server:
<?php $input = file_get_contents('php://input'); print("Post length: " . strlen($input) . "\n"); print("Hex: \n"); print(bin2hex($input)); print("\nText: \n"); print($input); print("\n"); ?>