How to use post() in qt? - qt

This is my program. In this program I want to send request to a website (for example: http://www.adobe.com/products/muse.html)
I want to show the html code that return me in plain text box.
QUrl url("http://www.adobe.com/products/muse.html")
I want to give html code in "thisfile"
file.setFileName("thisfile.html");
if (!file.open(QIODevice::WriteOnly))
{
std::cerr << "Error: Cannot write file "
<< qPrintable(file.fileName()) << ": "
<< qPrintable(file.errorString()) << std::endl
return false;
}
http.setHost(url.host(),80);
http.post(url.toString(),"term=yyyy&loc=en_us&siteSection=products%3Amuse",&file);
This code doesn't work correctly and when I show the file give me false html code. What do I have to do?

Use http.get() instead of http.post() as POST method requires to set other Headers used by server.
QHttp::get() method is asynchronous too.
As your case is simple enough just to retrieve HTML response, you should go for HTTP GET IMHO. See difference between GET and POST method.
And if you have to use HTTP POST only, then check this.

QNetworkRequest request;
request.setUrl(QUrl("thisfile.html"));
QNetworkReply *reply = manager->post(request, "term=yyyy&loc=en_us&siteSection=products%3Amuse");
connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));
Look at QNetworkAccessManager at qt docs
You have to read information and save it to file at readyRead function

Related

Cross origin error with QNetwork webassembly

I am trying to make a post/get call using QNetworkAccessManager in my c++ code which is exposed to webassembly using emscripten.
When the exposed function is compiled and loaded in Javascript, the requests are getting blocked due to cross-origin request.
I am running the local server from the folder that contains wasm, js and html files.
[Edited]: After some reading on CORS, I tried by adding additional header parameters to request:
request.setRawHeader("Access-Control-Request-Origin", "*");
But this also didn't work.
QNetworkRequest request(this->server);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
request.setRawHeader("Access-Control-Allow-Origin", "*"); request.setRawHeader("Access-Control-Allow-Methods", "POST");
// building the json and network request object
QByteArray byte_payload = QJsonDocument(payload).toJson();
QEventLoop loop;
QObject::connect(&manager, &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
loop.exec();
std::cout << "Request completed" << std::endl;
QByteArray reponse = reply->readAll();
std::cout << reponse.toStdString() << std:: endl;
Could you let me know how to resolve this?
[Edited]:
I tried to enable the node server for cros by using cors package. This enables the first OPTIONS call to succeed but the actual POST call that happens is send with incorrect payload.

QNetworkReply error "Connection closed" when getting a simple URL

I'm trying to make a simple file downloader. Here is my code segment for downloading a URL; This code works fine, if I try to get simple URLs like "http://stackoverflow.com".
But when I specify URLs which redirects, it throws an error saying "Connection closed".
//Sets a sample URL which redirects.
QString url = "http://downloads.sourceforge.net/project/gretl/gretl/1.9.92/gretl-1.9.92.tar.xz"
QNetworkAccessManager * networkAccessManager = new QNetworkAccessManager(this);
QNetworkRequest * networkRequest = new QNetworkRequest(QUrl(url));
//Getting the URL
QNetworkReply * networkReply = networkAccessManager->get(*networkRequest);
Additionally I've connected the following signal-slot to recognize network errors:
//Connects networkReply object's error signal to a slot which prints the error.
connect(networkReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(printError(QNetworkReply::NetworkError)));
Here is the slot which prints errors if networkReply's error signal is emitted:
void printError(QNetworkReply::NetworkError code)
{
qDebug() << "Network Error Code: " << code;
qDebug() << networkReply->errorString();
}
Because of this error, networkReply object never receives any header.
My need is to read the HTTP status code by this method: QNetworkReply::attribute(QNetworkRequest::HttpStatusCodeAttribute)
I can't read the HTTP Status code, because I don't get the headers.
Can anyone say whats going on?
Thanks in advance! :)
Here and here are good examples of handling this scenario - basically you add a slot for finished signal, then check the HTTP status code for 301 and/or QNetworkRequest::RedirectionTargetAttribute attribute to see if you are being redirected and if so issue a new request for the redirect link.

QNetworkAccessManager sends GET two times

I've got some class to interfere with HTTP-server.
Here is meaningfull code parts:
const QString someClass::BASEURL = QString("http://127.0.0.1:8000/?");
someClass::someClass():
manager(new QNetworkAccessManager(this))
{
}
QNetworkReply *someClass::run(QString request)
{
qDebug() << request;
QEventLoop loop;
QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), &loop, SLOT(quit()));
QNetworkReply *res = manager->get(QNetworkRequest(QUrl(BASEURL + request)));
loop.exec();
return res;
}
When I call method run(), sometimes (not every time) the are two identical GET-requests
(I looked with tcpdump). qDebug() executes 1 time.
Is there some error in my code? I can't see any possible explanation.
UPDATE:
After some tcpdump ouptut research.
After second request it sends packet with RST flag as an answer to FIN.
But I still can see no difference in TCP-streams that triggers the problem and that doesn't.
F.e. here is wireshark's output. Stream 8 went well. Stream 11 was duplicated with Stream 12.
I'm stuck with this. Maybe it's some protocol errors from server-size, I'm not sure. Or maybe it's a bug in QNetworkAccessManager.
Have you tried rewriting you code to be more asynchronous without using QEventLoop in a local scope? Your code looks good to me, but there might be some weird QT bug that you running into in the way it queues up requests for processing and using QEventLoop in the local scope. I usually use QNetworkAccessManager in the following manner to send GET and POST requests:
void someClass::run(QString request)
{
qDebug() << request;
QObject::connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(on_request_complete(QNetworkReply*)));
QNetworkReply *res = manager->get(QNetworkRequest(QUrl(BASEURL + request)));
}
void someClass::on_request_complete(QNetworkReply* response)
{
// Do stuff with your response here
}

Reading HTTP headers

I am trying to connect my application with a web service and here ,a user suggested to send custom headers back to my application.
I am using this code
void Coonnec::serviceRequestFinished(QNetworkReply *reply)
{
QByteArray bytes = reply->readAll();
if (reply->error() != QNetworkReply::NoError) {
qDebug() << "Reply error: " + reply->errorString();
}
else
{
qDebug() << "Uploaded: " + QDateTime::currentDateTime().toString();
qDebug() << reply->rawHeaderList();
}
reply->close();
bytes.clear();
reply->deleteLater();
}
from php i send this header
header('XAppRequest-Status: complete');
When running the application i can see that i get this header but i can't take the value of it cause
reply->rawHeader(bytes);
returns nothing.
How can i take the value 'complete'?
I suggest to connect a slot to the void QNetworkReply::metaDataChanged () signal of your reply.
The Qt doc says
This signal is emitted whenever the metadata in this reply changes.
metadata is any information that is not the content (data) itself,
including the network headers. In the majority of cases, the metadata
will be known fully by the time the first byte of data is received.
However, it is possible to receive updates of headers or other
metadata during the processing of the data.
I do use web-services/client with Qt and I noticed that some header's information are not available when I expected it to be ! I had to 'wait' for this signal to check the header content.

Whats the problem with my code (http post)

i am developing a simple application which uploads image to yfrog.com.(These images will be reflected in twitter account). Here is my code. but it is not working. I am not getting response from server.
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkRequest request(QUrl("http://yfrog.com/api/uploadAndPost"));
QByteArray data;
QUrl params,params1;
QFile file("some image path");
QString boundary("-----abcde12345");
QString body = "\r\n--" + boundary + "\r\n";
params.addQueryItem("username",twitterusername);
params.addQueryItem("password",twitterpassword);
params.addQueryItem("message",some message...);
params.addQueryItem("key",mydeveloperkey);
data.append(body);
data.append(params.toString());
QByteArray ba;
ba=file.readAll();
QString body1(ba);
params1.addQueryItem("media",body1);
data.append(params1.toString());
data.append(body);
request.setRawHeader("Content-Type","multipart/form-data; boundary=-----abcde12345");
request.setHeader(QNetworkRequest::ContentLengthHe ader,data.size());
QNetworkReply *reply = manager->post(request,data);
reply->waitForReadyRead(-1);
qDebug() << "replay :"<<reply->readAll();
If i checked the requested TCP packets from wireshark, it is giving a error message like 'malformed packets'.
For reference : http://code.google.com/p/imageshacka...GuploadAndPost
Please any body help regarding this. Where i am doing wrong?
QNetworkReply::waitForReadyRead does not have an implementation so it always refers the base class waitForReadyRead() (in this case QIODevice). In the base class, you will see that waitForReadyRead always returns FALSE.
From the docs, you would have to instead use the readRead() signal in QNetworkReply and read the data when the slot is called.
QNetworkReply *reply = manager->get(request);
connect(reply, SIGNAL(readyRead()), this, SLOT(slotReadyRead()));

Resources