QNetworkReply Never emit a finished signal - c++

I am writing a simple qt network application. I try to read the data from the QNetworkReply but it seems that the finished signal never emit. What happens?
QByteArray utils::Login(QString account)
{
QNetworkAccessManager* manager = new QNetworkAccessManager();
QNetworkRequest* request = new QNetworkRequest();
request->setUrl(QUrl(Urls::loginUrl));
request->setRawHeader("Host", "10.136.2.5");
request->setRawHeader("Referer", "http://10.136.2.5/jnuweb/");
request->setRawHeader("Content-Type", "application/json; charset=utf-8");
request->setRawHeader("Connection", "keep-alive");
request->setRawHeader("X-Requested-With", "XMLHttpRequest");
request->setRawHeader("Accept", "*/*");
request->setRawHeader("Accept-Encoding", "deflate");
QJsonObject* requestContent = new QJsonObject();
requestContent->insert("user", QJsonValue(account));
requestContent->insert("password", QJsonValue(Urls::initPassword));
QNetworkReply* reply = manager-> post(*request, QJsonDocument(*requestContent).toJson(QJsonDocument::Compact));
QObject::connect(reply, &QNetworkReply::finished, [=]()
{
QList<QPair<QByteArray, QByteArray>> responses = reply -> rawHeaderPairs();
qDebug() << responses;
});
}

Related

QNetworkAccessManager send PUT request with JSON

I want to send a put request with JSON body, but with QNetworkAccessManager doesn't have the option to send a request with JSON so I converted it to QByteArray, the structure of the body, when converted to QByteArray, is not a JSON format so that I received an Error with
"Error downloading https://example.api.com/something/DataSet('123456780XYZ') - server replied: Forbidden"
The JSON format I want is like this:
{
"d": {
"Duration": "0.000",
"Id": "123456780XYZ",
"LoadCumulLimit": "0.000",
"Notes": "send from postman in Json format"
}
}
Here is what did I do
QJsonObject data;
data["Duration"] = workplace->data["duration"];
data["Id"] = id;
data["LoadCumulLimit"] = workplace->data["load_cumul_limit"];
data["Notes"] = workplace->dataText["Notes"];
QJsonObject newData;
newData["d"] = data;
QJsonDocument doc(newData);
qDebug() << url;
QByteArray finalData = doc.toJson();
qDebug() << finalData;
reply = manager->put(request, finalData);
connect(reply, &QNetworkReply::finished, [=](){
if(reply->error() == QNetworkReply::NoError){
QString contents = QString::fromUtf8(reply->readAll());
qDebug() << contents;
}
else{
QString err = reply->errorString();
qDebug() << err;
}
reply->deleteLater();
});
But I received the QByteArray like this:
"{\n \"d\": {\n \"Duration\": 8,\n \"IgelId\": \"123456780XYZ\",\n \"LoadCumulLimit\": 25,\n \"Notes\": \"send from IGEL\"\n }\n}\n"

Get bad request from Google calendar API

I'm trying to insert an event to google calendar using Qt C++.
Before inserting events, I am able to clear the primary calendar using these lines
const QUrl clearPrimaryUrl("https://www.googleapis.com/calendar/v3/calendars/primary/clear");
void GoogleWrapper::clearPrimaryCalendar()
{
QNetworkReply *reply = google.post(clearPrimaryUrl);
connect(reply, &QNetworkReply::finished, [=]()
{
reply->deleteLater();
if(reply->error() != QNetworkReply::NoError)
{
qCritical() << "Google error:" << reply->errorString();
return;
}
emit primaryCalendarCleared();
});
}
google is an QOAuth2AuthorizationCodeFlow object.
Now to insert events, I use these lines:
const QUrl insertEventUrl("https://www.googleapis.com/calendar/v3/calendars/primary/events");
void GoogleWrapper::insertEvent(const QByteArray &eventData)
{
qDebug() << eventData;
QNetworkReply *reply = google.post(insertEventUrl, eventData);
connect(reply, &QNetworkReply::finished, [=]()
{
reply->deleteLater();
if(reply->error() != QNetworkReply::NoError)
{
qCritical() << "Google error:" << reply->errorString();
return;
}
emit eventInserted();
});
}
But the output I received from qCritical was always Error transferring https://www.googleapis.com/calendar/v3/calendars/primary/events - server replied: Bad Request.
I tried output the eventData to a file and copy paste it to Google's try this API and the below json data works perfectly
{
"description": "some teacher name",
"end": {
"dateTime": "2018-12-19T11:15:00Z"
},
"location": "Room",
"start": {
"dateTime": "2018-12-19T09:30:00Z"
},
"summary": "Subject Name"
}
Anyone have any idea what I did wrong?
The issue is solved thanks to #thuga's comment.
My code was missing the line
google.setContentType(QAbstractOAuth2::ContentType::Json);

Qt network request auto adding unexpected question mark

I am trying to send http POST request. Here is code snippets:
const QUrl URL("https://httpbin.org/post");
QNetworkRequest req(URL);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery urlQuery;
urlQuery.addQueryItem ("username", username);
urlQuery.addQueryItem ("password", password);
QUrl params;
params.setQuery (urlQuery);
mNetReply = mNetMan->post(req, params.toEncoded());
and here is the response output:
QJsonObject({"args":{},"data":"","files":{},"form":{"?username":"xyz","password":"xyz"},"headers":{"Accept-Encoding":"gzip, deflate","Accept-Language":"en-US,*","Connection":"close","Content-Length":"28","Content-Type":"application/x-www-form-urlencoded","Host":"httpbin.org","User-Agent":"Mozilla/5.0"},"json":null,"origin":"*.*.*.*","url":"https://httpbin.org/post"})
My problem is , qt automatically adding a ? mark in first queryItem.
For what it's worth still, because an answer was not given:
Don't use the conversion to a QUrl, using the QUrlQuery directly solved the problem for me.
urlQuery.toString(QUrl::FullyEncoded).toUtf8()
in stead of
params.toEncoded()
Total snippet updated:
const QUrl URL("https://httpbin.org/post");
QNetworkRequest req(URL);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QUrlQuery urlQuery;
urlQuery.addQueryItem ("username", username);
urlQuery.addQueryItem ("password", password);
mNetReply = mNetMan->post(req, urlQuery.toString(QUrl::FullyEncoded).toUtf8());

Qt Network Access Manager JSON Get Response

I'm trying to pull JSON data from a URL using the Qt framework, and I've run into some issues with getting a return from the get request. I've seen multiple questions asked regarding my issue, but none of the given solutions has solved my problem.
So I have a button that, once clicked, should execute the get request. Here's my code.
//When button is pressed
void Test1::onClickCapture()
{
qDebug() << "Capture Clicked!!";
toPopulate();
}
//Code to execute the connection
void Test1::toPopulate() {
qDebug() << "Populating!";
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QNetworkRequest request;
QUrl url("https://jsonplaceholder.typicode.com/posts/1");
request.setUrl(url);
QNetworkReply *reply = manager->get(request);
connect(reply, &QNetworkReply::readyRead, this, &Test1::onResult);
}
//And finally, my onResult slot
void Test1::onResult() {
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
return;
}
qDebug() << "Response!";
}
Every time I debug the code, it never gets to my onResult slot.
I also get this error, which may be relevant.
QObject::connect: Cannot connect (null)::aboutToQuit() to QNativeWifiEngine::closeHandle()
I have modified your code. It's working fine for me:
//Code to execute the connection
void MainWindow::toPopulate() {
qDebug() << "Populating!";
QNetworkAccessManager* manager = new QNetworkAccessManager(this);
QNetworkRequest request;
QUrl url("https://jsonplaceholder.typicode.com/posts/1");
request.setUrl(url);
QNetworkReply *reply = manager->get(request);
connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloading(qint64,qint64)));
connect(reply, SIGNAL(finished()), this, SLOT(onResult()));
}
void MainWindow::downloading(qint64 bytesReceived, qint64 bytesTotal) {
qDebug() << "Downloading " << bytesReceived/bytesTotal*100 << " %.";
}
//And finally, my onResult slot
void MainWindow::onResult() {
QNetworkReply* reply = qobject_cast<QNetworkReply*> (QObject::sender());
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Error downloading. " << reply->errorString();
return;
}
reply->deleteLater();
qDebug() << "Response! " << reply->readAll();
}
Result:
Populating!
Downloading -29200 %.
Downloading 100 %.
Response! "{\n \"userId\": 1,\n \"id\": 1,\n \"title\": \"sunt aut facere repellat provident occaecati excepturi optio reprehenderit\",\n \"body\": \"quia et suscipit\\nsuscipit recusandae consequuntur expedita et cum\\nreprehenderit molestiae ut ut quas totam\\nnostrum rerum est autem sunt rem eveniet architecto\"\n}"

Read local file from QWebView using Ajax request

I am developing a Qt/C++ program which encapsulates an HTML5/JQuery web app.
I used to make Ajax requests to read files from a server. But now, I would like Qt to read a file from the local disk and send its content to my web app.
I think I need Qt to catch Ajax requests from the web app and return the file content as the Ajax request result.
The problem is I don't know how to do. For now, I've not found anything about that on google.
Any help is welcome!
I finally found how to do it. I overrode QNetworkAccessManager.
MyQNetworkAccessManager .h:
class MyQNetworkAccessManager : public QNetworkAccessManager
{
Q_OBJECT
protected:
virtual QNetworkReply * createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData = 0);
};
MyQNetworkAccessManager.cpp:
QNetworkReply * MyQNetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData) {
QUrl url = req.url();
QString path = url.path();
if (op == QNetworkAccessManager::GetOperation && path.endsWith("xml")) {
QUrl newUrl;
if(path.endsWith("..")) {
newUrl.setUrl("...");
}
else if(path.endsWith("...")) {
newUrl.setUrl("...");
}
else {
newUrl = url;
}
return QNetworkAccessManager::createRequest(QNetworkAccessManager::GetOperation, QNetworkRequest(newUrl));
}
else
{
return QNetworkAccessManager::createRequest(op, req, outgoingData);
}
}
MainWindow.cpp:
// ....
QWebView *qWebView = new QWebView();
QWebPage *page = qWebView->page();
MyQNetworkAccessManager *networkManager = new MyQNetworkAccessManager();
page->setNetworkAccessManager(networkManager);
qWebView->setPage(page);
qWebView->load(QUrl("..."));
// ....