Correct Format for Http Post Using Qnetworkrequest

Correct format for HTTP POST using QNetworkRequest

This is not the right way to write your HTTP request. The following piece of code is more correct :

connect(m_qnam, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleNetworkData(QNetworkReply*)));
connect(m_qnam,SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)), this, SLOT(handleSSLErrors(QNetworkReply*)));

// Build your JSON string as usual
QByteArray jsonString = "{\"method\":\"AuthenticatePlain\",\"loginName\":\"username@domain.com\",\"password\":\"mypass\"}";

// For your "Content-Length" header
QByteArray postDataSize = QByteArray::number(jsonString.size());

// Time for building your request
QUrl serviceURL("https://www.superService.com/api/1.7/ssapi.asmx");
QNetworkRequest request(serviceURL);

// Add the headers specifying their names and their values with the following method : void QNetworkRequest::setRawHeader(const QByteArray & headerName, const QByteArray & headerValue);
request.setRawHeader("User-Agent", "My app name v0.1");
request.setRawHeader("X-Custom-User-Agent", "My app name v0.1");
request.setRawHeader("Content-Type", "application/json");
request.setRawHeader("Content-Length", postDataSize);

// Use QNetworkReply * QNetworkAccessManager::post(const QNetworkRequest & request, const QByteArray & data); to send your request. Qt will rearrange everything correctly.
QNetworkReply * reply = m_qnam->post(request, jsonString);

How can I POST data to a url using QNetworkAccessManager

I used:

QByteArray postData;
postData.append("param1=string&");
postData.append("param2=string");

So & instead of newline after each parameter.

HTTP POST request in QT using QNetworkAccessManager

It seems that you do not know the following concepts:

  • Qt Network like all Qt modules work asynchronously so don't think about getting the information synchronously.

  • Qt needs an eventloop, in this case QCoreApplication is enough.

  • If you want to do periodic tasks then you should use a QTimer instead of a while loop with Sleep.

Considering the above, the solution is:

httpmanager.h

#ifndef HTTPMANAGER_H
#define HTTPMANAGER_H

#include <QObject>

class QNetworkReply;
class QNetworkAccessManager;

class HTTPManager : public QObject
{
Q_OBJECT
public:
HTTPManager(QObject *parent=nullptr);
~HTTPManager();
void postData(QString str);
private Q_SLOTS:
void replyFinished(QNetworkReply *rep);
private:
QNetworkAccessManager * manager;
QNetworkReply *reply;
};

#endif // HTTPMANAGER_H

httpmanager.cpp

#include "httpmanager.h"

#include <QNetworkAccessManager>
#include <QNetworkReply>

HTTPManager::HTTPManager(QObject *parent)
: QObject(parent), manager(new QNetworkAccessManager(this))
{
connect(manager, &QNetworkAccessManager::finished,this, &HTTPManager::replyFinished);
}

HTTPManager::~HTTPManager()
{
}

void HTTPManager::postData(QString str)
{
QNetworkRequest request;
QByteArray data = str.toUtf8();

QUrl url;

url.setScheme("http");
url.setHost("test.vivcorefmms.com");
url.setPath("/node/filter_data");
request.setUrl(url);
request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
manager->post(request, data);
}

void HTTPManager::replyFinished(QNetworkReply *rep)
{
QByteArray bts = rep->readAll();
QString str = QString::fromUtf8(bts);
qDebug().noquote() << "Reply:"<<str;
rep->deleteLater();
}

main.cpp

#include "httpmanager.h"

#include <QCoreApplication>
#include <QTimer>

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
HTTPManager manager;
QTimer timer;
timer.setInterval(1000);
QObject::connect(&timer, &QTimer::timeout, [&manager](){
manager.postData("A==##1802201049565471101000000N0526.874000E07256.4380000101035070#&11397002170466466466466466&12208004230370336441514488!~~~0");
});
timer.start();
return a.exec();
}
Reply: <head><title>Not Acceptable!</title></head><body><h1>Not Acceptable!</h1><p>An appropriate representation of the requested resource could not be found on this server. This error was generated by Mod_Security.</p></body></html>

And that is caused because a user-agent is missing so modifying it to:

request.setRawHeader("Content-Type", "application/x-www-form-urlencoded");
request.setRawHeader("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.47 Safari/537.36");
manager->post(request, data);

Obtaining the following:

Reply: <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Database Error</title>
<style type="text/css">

::selection { background-color: #E13300; color: white; }
::-moz-selection { background-color: #E13300; color: white; }

body {
background-color: #fff;
margin: 40px;
font: 13px/20px normal Helvetica, Arial, sans-serif;
color: #4F5155;
}

a {
color: #003399;
background-color: transparent;
font-weight: normal;
}

h1 {
color: #444;
background-color: transparent;
border-bottom: 1px solid #D0D0D0;
font-size: 19px;
font-weight: normal;
margin: 0 0 14px 0;
padding: 14px 15px 10px 15px;
}

code {
font-family: Consolas, Monaco, Courier New, Courier, monospace;
font-size: 12px;
background-color: #f9f9f9;
border: 1px solid #D0D0D0;
color: #002166;
display: block;
margin: 14px 0 14px 0;
padding: 12px 10px 12px 10px;
}

#container {
margin: 10px;
border: 1px solid #D0D0D0;
box-shadow: 0 0 8px #D0D0D0;
}

p {
margin: 12px 15px 12px 15px;
}
</style>
</head>
<body>
<div id="container">
<h1>A Database Error Occurred</h1>
<p>Error Number: 1048</p><p>Column 'node_id' cannot be null</p><p>INSERT INTO `node_info` (`node_info_id`, `node_id`, `message_id`, `gsm`, `wifi`, `gprs`, `_3g`, `bluetooth`, `gps`, `emergency_code`, `env_temperature`, `env_humidity`, `env_pressure`, `gps_speed`, `gps_latitude`, `gps_longitude`, `date`, `time`, `number_of_compartment`, `number_of_dispense`, `sys_date`, `sys_time`) VALUES ('', NULL, '654', '7', '0', '1', '1', '1', '0', '0', '03', '507', '0101', '0', NULL, NULL, '#18022', '010495', 15, '', '2020-03-28', '23:31:10')</p><p>Filename: models/Model_master.php</p><p>Line Number: 156</p> </div>
</body>
</html>

And the message points out the error:

Error Number: 1048

Column 'node_id' cannot be null

INSERT INTO `node_info` (`node_info_id`, `node_id`, `message_id`, `gsm`, `wifi`, `gprs`, `_3g`, `bluetooth`, `gps`, `emergency_code`, `env_temperature`, `env_humidity`, `env_pressure`, `gps_speed`, `gps_latitude`, `gps_longitude`, `date`, `time`, `number_of_compartment`, `number_of_dispense`, `sys_date`, `sys_time`) VALUES ('', NULL, '654', '7', '0', '1', '1', '1', '0', '0', '03', '507', '0101', '0', NULL, NULL, '#18022', '010495', 15, '', '2020-03-28', '23:18:26')

Filename: models/Model_master.php

Line Number: 156

Which shows an error caused by the data sent that seems not to comply with the processing, that is, A==##1802201049565471101000000N0526.874000E07256.4380000101035070#&11397002170466466466466466&12208004230370336441514488!~~~0 that seems to be not well formed

How do I send payload via a QNetworkAccessManager for post?

I found this
Correct format for HTTP POST using QNetworkRequest

QByteArray jsonString = "{\"method\":\"AuthenticatePlain\",\"loginName\":\"username@domain.com\",\"password\":\"mypass\"}";

QNetworkReply * reply = m_qnam->post(request, jsonString);

Send POST via Qt shrink the post content

The issue was coming from the sent data : I was sending chars that was interpreted as querys like = or &.

I just remove its from the string using this :

content.remove("[=|&]");

and it worked well.

How to send a POST request in Qt with the JSON body

QHttpMultiPart is used to send MIME multipart message but in this case it is not required to send that type of information. Instead, you should use QJsonDocument to create the json and convert it to QByteArray:

QNetworkAccessManager *mgr = new QNetworkAccessManager(this);
const QUrl url(QStringLiteral("http://myserver.com/api"));
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");

QJsonObject obj;
obj["key1"] = "value1";
obj["key2"] = "value2";
QJsonDocument doc(obj);
QByteArray data = doc.toJson();
// or
// QByteArray data("{\"key1\":\"value1\",\"key2\":\"value2\"}");
QNetworkReply *reply = mgr->post(request, data);

QObject::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();
});

Make HTTP POST request with a list of named parameters in Qt

QUrl params;

params.addQueryItem("key1", "value1");
params.addQueryItem("key2", "value2");

QUrl resource("http://server.com/form.php");
QNetworkAccessManager* manager = new QNetworkAccessManager(this);

connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(handleEndOfRequest(QNetworkReply*)));

QNetworkRequest request(resource);
//Force Content-Type header
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");

manager->post(request, params.encodedQuery());

This code assumes that your current object is a QObject (passed as a parent for QNeworkAccessManager and slots declaration)

Qt Simple Post Request

Connect the QNetworkAccessManager signal finished to your slot and using QNetworkReply you should read all the contents of the webpage.

Here is a get example it can be easily adapted for the post method.

void MainWindow::on_pushButton_clicked()
{
QNetworkAccessManager * mgr = new QNetworkAccessManager(this);
connect(mgr,SIGNAL(finished(QNetworkReply*)),this,SLOT(onfinish(QNetworkReply*)));
connect(mgr,SIGNAL(finished(QNetworkReply*)),mgr,SLOT(deleteLater()));

mgr->get(QNetworkRequest(QUrl("http://www.google.com")));

}

void MainWindow::onfinish(QNetworkReply *rep)
{
QByteArray bts = rep->readAll();
QString str(bts);
QMessageBox::information(this,"sal",str,"ok");

}

Http POST, selecting the page using Qt

The line

url_str = "/page_wanted?parameters=5&t=3";

is missing a plus sign :D try

url_str += "/page_wanted?parameters=5&t=3";

and you should be good to go...

How do I write a Qt HTTP GET request?

You need three things:

  • QNetworkAccessManager * manager; -> To send us a request.
  • QNetworkRequest request; -> what type of demand? get, post, ...
  • QNetworkReply. -> What's the answer?

for more detail:

  • http://doc.qt.io/qt-5/qnetworkaccessmanager.html#details

  • http://doc.qt.io/qt-5/qnetworkrequest.html#details

  • http://doc.qt.io/qt-5/qnetworkreply.html#details

for example:

.cpp

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

manager = new QNetworkAccessManager();
QObject::connect(manager, &QNetworkAccessManager::finished,
this, [=](QNetworkReply *reply) {
if (reply->error()) {
qDebug() << reply->errorString();
return;
}

QString answer = reply->readAll();

qDebug() << answer;
}
);
}

void MainWindow::on_pushButton_clicked()
{
request.setUrl(QUrl("http://url"));
manager->get(request);
}

MainWindow::~MainWindow()
{
delete ui;
delete manager;
}

.h file

private:
Ui::MainWindow *ui;
QNetworkAccessManager *manager;
QNetworkRequest request;

EDIT LAMBDA SLOT:
if not use lambda SIGNAL SLOT.

Discribe one slot in your .h file
for example:

private slots:
void managerFinished(QNetworkReply *reply);

in .cpp constructor replace lambda to

QObject::connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(managerFinished(QNetworkReply*)));

now in your slot:

void MainWindow::managerFinished(QNetworkReply *reply) {
if (reply->error()) {
qDebug() << reply->errorString();
return;
}

QString answer = reply->readAll();

qDebug() << answer;
}


Related Topics



Leave a reply



Submit