Cross origin error with QNetwork webassembly - qt

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.

Related

How could I make grpc server do other work when there is no client calls?

I have a simple function that is served with grpc, the starting method of this service is like this:
void start_server() {
string addr("0.0.0.0:50002");
ImageServiceImpl service;
ServerBuilder builder;
builder.AddListeningPort(addr, grpc::InsecureServerCredentials());
builder.RegisterService(&service);
builder.SetMaxSendMessageSize(1L << 31);
builder.SetMaxReceiveMessageSize(1L << 31);
std::unique_ptr<grpc::Server> server(builder.BuildAndStart());
std::cout << "service started, listening to: " << addr << std::endl;
server->Wait();
}
It is a standard grpc server. My problem is that, I need the server to execute other programs when there is no client request called. And when a client request comes, the server program would be 'interrupted' and the server will deal with the request. After dealing with the request, the server continues executing its 'leisure time' program. The problem is that the program would block at the server->Wait(), thus when there is not client request comes, the server can do nothing but wait, which is not what I need it to do.
I hope I have expressed myself clearly. How could I do this with grpc ?
Does running a thread before server->Wait() not solve this problem?
On .NET C #, I solved it like this:
...
// Start other work
MainTask mainTask = new MainTask(configurator, _gRPCManager);
Thread mainThread = new Thread(mainTask.Run);
mainThread.IsBackground = true;
mainThread.Start();
// Start gRPS
CreateHostBuilder(args, configurator).Build().Run();

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
}

How to use post() in 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

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.

Resources