Sending HTTP Header Info with Qt QNetworkAccessManager - qt

I have the following code, and I would like to add some HTTP header info along with the call. Anyway that I can do that?
void NeoAPI::call(QString apiCall) {
if (this->ApiCall.contains(apiCall)) {
QNetworkAccessManager* manager = new QNetworkAccessManager(0);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(netReplyFinished(QNetworkReply*)));
QUrl url = this->ApiCall[apiCall];
url.addQueryItem("memberid","76710"); // Set for backdoor debugging
manager->get(QNetworkRequest(url));
} else {
this->requestResultText = QString("Call %1 doesn't exist").arg(apiCall);
}
}
void NeoAPI::netReplyFinished(QNetworkReply *netReply) {
if (netReply->error() == QNetworkReply::NoError) {
this->requestResultText = netReply->readAll();
} else {
this->requestResultText = "API Call Failed";
}
QMessageBox messageBox;
messageBox.setText(this->requestResultText);
messageBox.exec();
//delete netReply;
}
Also, if I wasn't using these inside a class, what would the this in the connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(netReplyFinished(QNetworkReply*))); be?
Thanks!

Yes, see the documentation of QNetworkRequest.
You'll want to do something like:
QNetworkRequest request(url);
request.setHeader( QNetworkRequest::ContentTypeHeader, "some/type" );
request.setRawHeader("Last-Modified", "Sun, 06 Nov 1994 08:49:37 GMT");
manager->get( header );
Also, if I wasn't using these inside a
class, what would the this in the
connect(manager,
SIGNAL(finished(QNetworkReply*)),
this,
SLOT(netReplyFinished(QNetworkReply*)));
be?
It wouldn't be anything. To connect a signal to a slot, that slot must be a member function of some object. The Qt primer on signals and slots explains this.

Related

How to properly disconnect signal ready read from QNetworkreply

following issue abot my code. For unserstanding reason I connect to an event stream which publish every minute the actual status of a device under the url of : "urldevice"/event-stream. I connect a slot to the signal "readyread" and will disconnect. But still I am calling the disconnect function I recieve information in the cnnected slot.
Here is my code
QNetworkRequest request(_url + "events");
request.setRawHeader("Accept", "text/event-stream");
request.setHeader(QNetworkRequest::UserAgentHeader, "Plugin");
if (_token != "") {
request.setRawHeader("accept", "*/*");
QString token = "Bearer " + _token;
request.setRawHeader("Authorization", token.toUtf8());
}
request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
request.setAttribute(QNetworkRequest::CacheLoadControlAttribute,
QNetworkRequest::AlwaysNetwork); // Events shouldn't be cached
_sseReply = _sseNetworkManager->get(request);
QObject::connect(_sseReply, &QNetworkReply::readyRead, this, &streamReceived);
void streamReceived() {
if (_sseReply->error() == QNetworkReply::NoError) {
qCDebug(m_logCategory) << "streamrecieved";
} else {
qCDebug(m_logCategory) << "disconnect";
}
}
void disconnect() {
if (_sseReply->isRunning()) {
_sseReply->abort();
_sseReply->close();
_sseNetworkManager->disconnect(_sseReply,&QNetworkReply::readyRead,this,&streamReceived);
_sseNetworkManager->disconnect();
_sseReply->disconnect();
qCDebug(m_logCategory) << "isrunnung";
}
_flagStandby = true;
QObject::disconnect(_sseReply, &QNetworkReply::readyRead, this, &streamReceived);
}
after caling disconnect() I see all the time
disconnect
in my log
How do I properly disconnect from the signal???

Using QNetworkAccessManager::post to transfer file got QIODevice: device not open

I am using Qt 5.7.0 on Ubuntu 16.04.1 x64.
When I try to using QNetworkAccessManager::post() to transfer file, it will got Error "QIODevice:device not open".
It's strange that release version of the program will go wrong certainly, while the same problem only occur after a long time running(look like that) in debug version.
Here is relative function:
QHttpMultiPart* PacketFactory::getPacket(QString id, QString imgPath) {
QHttpMultiPart *pMultiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart idPart;
idPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
idPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"id\""));
idPart.setBody(id.toUtf8());
// some text/plain part
...
QFile *imgFile = new QFile(imgPath);
imgFile->setParent(pMultiPart);
Q_ASSERT(imgFile->open(QIODevice::ReadWrite));
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"img\"; filename=\"1.jpg\""));
imagePart.setBodyDevice(imgFile);
pMultiPart->append(imagePart);
return pMultiPart;
}
Another:
QNetworkRequest NetManager::getRequest(int dst) {
QString url;
switch (op) {
case DST_LOCAL:
url = "http://127.0.0.1/query"
break;
...
}
return QNetworkRequest(QUrl(url));
}
Here is invoke code:
QNetworkRequest request = m_pNetManager->getRequest(NetManager::DST_LOCAL);
QHttpMultiPart *pMultiPart = PacketFactory::getPacket(...);
QNetworkReply *pReply = m_NetworkAccessManager.post(request, pMultiPart);
QObject::connect(pReply, SIGNAL(finished()), this, SLOT(handlePacket()));
pMultiPart->setParent(pReply);
Thanks for advices.

Index out of range when making XMLHttpRequest call

I'm facing an error I don't really understand.
var http = new XMLHttpRequest();
var url = "http://..........";
http.open("GET", url, true);
http.onreadystatechange = function() {
console.log("readyState=" + http.readyState);
if (http.readyState == 4) {
if (http.status == 200) {
console.log("ok");
} else {
console.log("not ok");
}
}
}
http.send();
QtCreator console log:
qml: readyState=2
qml: readyState=3
ASSERT failure in QList::at: "index out of range", file C:\Qt\5.5\mingw492_32\include/QtCore/qlist.h, line 510
In Wireshark, the request is made as expected and the page correctly downloaded. What am I doing wrong?
Edit:
I am trying to use same networkaccessmanager in C++ and QML.
I have a Login class to make a connection to a website. The I need to use the same manager to make other requests in QML.
I first thought the problem was about pointer or the way I call Login(), but with Wireshark, the login request and the one made via QML have the same session id. I deduced the problem was not that, but i'm probably wrong.
main.cpp
QQmlApplicationEngine engine;
.....
QNetworkAccessManager *networkmanager = new QNetworkAccessManager();
networkmanager = engine.networkAccessManager();
Login login(networkmanager);
login.h
.....
class Login : public QObject
{
Q_OBJECT
public:
explicit Login(QNetworkAccessManager *manager, QObject *parent = 0);
.....
private:
QNetworkAccessManager *m_manager;
.....
}
login.cpp
.....
Login::Login(QNetworkAccessManager *manager, QObject *parent) : QObject(parent)
{
m_manager = manager;
connect(m_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(slotRequestFinished(QNetworkReply*)));
}
.....

use `QNetworkAccessManager` post request

i use QNetworkAccessManager post request to a website:
void Spider::getProducts()
{
connect(&manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(getProducts(QNetworkReply*)));
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
request.setUrl(QUrl("http://www.example.com/query"));
for(int i = 0; i < categories.size(); ++i)
{
if(categories[i].isCategory())
{
isSubCategory = false;
emit manager.finished(reply);
}
else
{
for(int page_number = 0; page_number < categories[i].getPageCount(); ++i)
{
isSubCategory = true;
QJsonObject json;
json.insert("NValue", categories[i].getNValue());
json.insert("NodeId", categories[i].getNodeId());
json.insert("StoreId", categories[i].getStoreId());
json.insert("StoreType", categories[i].getStoreType());
json.insert("PageNumber", ++page_number);
json.insert("SubCategoryId", categories[i].getSubCategoryId());
QJsonDocument doc;
doc.setObject(json);
QByteArray request_body = doc.toJson();
manager.post(request, request_body);
}
}
}
}
when i run this program, at beginning, this program run normally, after running for a while, it will stop: neither terminated nor continue to run. i can not figure out why it behavior like this? is there anything that needed to be noticed when use QNetworkAccess? or i am refused by that website? ...
You are using the same QNetworkAccessManager object in a loop multiple times. It is incorrect. For each separate post request you need a separate QNetworkAccessManager object if you want to send requests in parallel. Else if you only want to use a single instance then you need to serialize your post requests by sending next post request when the previous ends in the finished slot.
Updated: Try out this code, it uses single QNetworkAccessManager object, you will need to check for correct place of i++ as per your needs
connect(&manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(getProducts(QNetworkReply*))); // add this to constructor of your program
void Spider::getProducts()
{
static int i = 0;
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
request.setUrl(QUrl("http://www.example.com/query"));
while(categories[i].isCategory())
{
isSubCategory = false;
i++;
}
if(i == categories.size())
{
emit allPostRequestsDone();
return;
}
else
{
i++;
if(page_number < categories[i].getPageCount())
{
isSubCategory = true;
QJsonObject json;
json.insert("NValue", categories[i].getNValue());
json.insert("NodeId", categories[i].getNodeId());
json.insert("StoreId", categories[i].getStoreId());
json.insert("StoreType", categories[i].getStoreType());
json.insert("PageNumber", ++page_number);
json.insert("SubCategoryId", categories[i].getSubCategoryId());
QJsonDocument doc;
doc.setObject(json);
QByteArray request_body = doc.toJson();
manager.post(request, request_body);
}
}
}
}

Qt QNetworkAccessManager and multiple QNetworkReply

I have two get QNetworkRequest.
I want to handle finished signals from different methods.
For example this is code in
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
GetUserData();
connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(GetUserDataCompleted(QNetworkReply*)));
GetMessages();
connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(GetMessagesCompleted(QNetworkReply*)));
}
This my one method
I have tried replay->deleteLater(); but same result
Please advice me something useful
void MainWindow::GetUserDataCompleted(QNetworkReply *replay)
{
if(replay->error() == QNetworkReply::NoError)
{
QString getData = replay->readAll();
QMessageBox msg;
if(getData == "1")
{
msg.setText("User Is not Exits");
}
else
{
QDomDocument doc;
if(doc.setContent(getData))
{
QDomElement domElem = doc.documentElement();
QDomNode n = domElem.firstChild();
while(!n.isNull()) {
QDomElement e = n.toElement(); // try to convert the node to an element.
if(!e.isNull()) {
msg.setText(e.namedItem("Image").childNodes().at(0).nodeValue());
msg.exec();
}
n = n.nextSibling();
}
}
replay->deleteLater();
}
}
}
You can create a RequestSender class whose role is looking after requests.
Each RequestSender object will handle one unique request. While creating the QNetworkRequest that will be sent, the RequestSender will "tag" its own request with the originatingObject attribute. This attribute indicates which object sent the request. When a RequestSender object receives a reply, it will look if it is the sender of the request via the originatingObject attribute. For further informations about originatingObject, you can refer to the documentation here : http://qt-project.org/doc/qt-4.8/qnetworkrequest.html#originatingObject
Below is an example of what you can do.
requestsender.hpp :
class RequestSender {
public:
RequestSender();
~RequestSender();
void createRequest(/* Request parameters */);
public slots:
void endRequest(QNetworkReply* replay);
};
requestsender.cpp :
RequestSender::RequestSender() {
connect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(endRequest(QNetworkReply*)));
}
RequestSender::~RequestSender() {
disconnect(nam, SIGNAL(finished(QNetworkReply*)), this, SLOT(endRequest(QNetworkReply*)));
}
void RequestSender::createRequest(/* Request parameters */) {
QNetworkRequest * myRequest = 0;
// Build myRequest with the request parameters
myRequest->setOriginatingObject(this);
nam->get(*myRequest);
}
void RequestSender::endRequest(QNetworkReply* replay) {
if (replay->request().originatingObject() != this) {
// That's not the request sent by the object -> stop the method here !
return;
}
// Treatments on replay
}
Every operation you do with your QNetworkAccessManager will return a QNetworkReply. This has also has an signal finished(). Maybe you can connect this signal to your different slots.

Resources