1

The following code uses QT's Network API to send HTTP request and get the response:

void AnotherHttpClient::finished(QNetworkReply *qNetworkReply)
{
    qDebug() << qNetworkReply->readAll();
}

void AnotherHttpClient::get(QString url)
{
    QNetworkAccessManager *man = new QNetworkAccessManager(this);
    connect(man, &QNetworkAccessManager::finished, this, finished);
    const QUrl qurl = QUrl(url);
    QNetworkRequest request(qurl);
    man->get(request);
}

I need to make this code synchronous and I need get method to return the qNetworkReply. How should I do this? BTW are there any other synchronous way to send Http request in QT?

Gandalf
  • 2,921
  • 5
  • 31
  • 44
  • 2
    Possible duplicate of [Qt synchronous QNetworkAccessManager get](https://stackoverflow.com/questions/11828322/qt-synchronous-qnetworkaccessmanager-get) – bznein Nov 04 '19 at 14:36
  • 1
    Why would you want to make it *not* asynchronous? You'll be blocking the event loop and make your application unresponsive.. – Jesper Juhl Nov 04 '19 at 14:45
  • @JesperJuhl I know that but I need this for an special use case. – Gandalf Nov 04 '19 at 14:47
  • @bznein I have tried that and That does not work furthermore the mentioned question is too vague and there has not been enough code presented, so I decided to ask this question to seek for help. – Gandalf Nov 04 '19 at 14:50
  • The answer really is "spin an event loop and stop it when the request becomes finished", so the linked answer is correct. How did it "not work" for you? – Botje Nov 04 '19 at 14:56

2 Answers2

5

You can do as following:

QNetworkAccessManager l_nm;
QUrl l_url ("http://foo.bar");
QNetworkRequest l_req(l_url);
QNetworkReply *l_reply = l_nm.get(l_req);
QEventLoop l_event_loop;
QObject::connect(l_reply, SIGNAL(finished()), &l_event_loop, SLOT(quit()));
l_event_loop.exec();

but using an event loop inside a Qt application is the worst idea ever.

JuanDeLosMuertos
  • 4,532
  • 15
  • 55
  • 87
  • But using nested event loop is not allowed for the web-assembly. In addition, if this is targeted only for desktop application, then connection is to be checked for failures too. – Ronak SHAH Aug 04 '20 at 04:56
  • it's a "bad idea" but totally supported by Qt desktop applications if you're aware of the downsides of a nested event loop. Also @RonakSHAH - finished() is always called even when an error occurs so one would only have to check l_reply->error() after the loop returns. – Shirkrin Apr 28 '22 at 16:27
  • 1
    If the url is invalid, this hangs indefinitely for me... – IceFire Dec 28 '22 at 10:42
2

This is another "ugly" way of doing it... but maybe less ugly than running custom event loop, you can actually add some "helpers" inside while loop and handle errors.

QNetworkRequest request(workingPath);
auto reply = m_WebCtrl.get(request);
uint count = 0;
bool waiting = reply->isFinished();
while (!waiting) {
    qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
    count++;
    waiting = reply->isFinished();
    QThread::msleep(1);
    if (count > 1000 * 10) {/// wait 10 seconds
        waiting = true;
    }
}
Adriaan
  • 17,741
  • 7
  • 42
  • 75
Dariusz
  • 960
  • 13
  • 36
  • 2
    compared to the nested event loop this is the worse alternative as qApp->processEvents() has the potential of never returning even if you filter out UserInputEvents. – Shirkrin Apr 28 '22 at 16:29
  • Hee good one, had no idea that it can happen. Well in that case hmmm no idea... maybe dont use processEvents, but not sure if then the NetworkRequest would still proces... hmmm – Dariusz Jun 17 '22 at 09:41