How to properly do a http GET request using QNetwo

2019-08-27 01:46发布

问题:

This is a follow up of this question. At first I thought the issue was resolved after checking out the example from the Qt wiki (I use the same code without a single change). However it appears that it's the URL that is the culprit. I tried using the links provided in this answer to test my http GET request. Using the Http Requester (Firefox addon for Http requests (GET, POST etc.)) and curl shows no issues with this link^:

$~: curl --request GET --url "http://httpbin.org/ip" 

For some reason Qt gets stuck and the readyRead()/finished() signals are never emitted.

As a result the request gets cancelled after some time due to socket timeout...For something that is really small and opened by Firefox in less than a second.

I'm far from an expert when it comes to Http stuff. I'd like to know why this behaviour occurs in Qt while there is no sign of it when working with other tools.

EDIT: I've also tested the problematic URLs using Python and its urllib

import urllib.request
res = urllib.request.urlopen("http://httpbin.org/ip").read().decode("utf-8") 

import xml.etree.ElementTree as ET
doc = ET.fromstring(res)

and it works just fine. Clearly there is something with Qt going on and/or me missing something when using it.

EDIT2: I've also tried another test service for HTTP requests - https://postman-echo.com. With curl there is no problem:

$~: curl --request GET --url "https://postman-echo.com/get?foo1=bar1&foo2=bar2"

For my surprise though there is no problem with Qt either! The only thing that I see here as a huge difference is that postman-echo.com uses HTTPS while the other URLs I've tried were HTTP. I exclude the https://www.qt.io which was the default URL in the Qt example and worked just fine (though it didn't have any parameters).

回答1:

Try executing that in an event loop. Here is something similar to what I do in a non-gui application:

QUrl req_url = QUrl(href);
QNetworkRequest request(req_url);

//request.setRawHeader("Content-Type", "application/json;utf8");
//q_nam is QNetworkAccessManager created earlier
QNetworkReply *reply = q_nam->get(request);

QEventLoop event_loop;
connect(q_nam, SIGNAL(finished(QNetworkReply * ) ), &event_loop, SLOT(quit() ) );
event_loop.exec(); // blocks stack until "finished()" has been called
event_loop.processEvents(QEventLoop::ExcludeUserInputEvents, 500 );//what events to processed and for how long
event_loop.exit();

QNetworkReply::NetworkError er = reply->error();
// ....continue handling


回答2:

I forgot to mention that I'm behind. Frankly I feel rather stupid for missing this and also not checking through the guest network at work (which circumvents the stupid proxy). A colleague of mine tried using HTTPS instead of HTTP (which is the original link). The HTTPS is also something that the proxy just lets go through without any issues. And it worked.

However a more neutral solution is (as my colleagues found out) to use QNetworkProxyFactory::setUseSystemConfiguration(true) which takes the proxy configuration that I have system-wide.