QNetworkReply - Strange error in enum, OperationCanceled instead of Timeout? - c++

My API server is turned off and i run following code.
I dont understand why QNetworkReply::OperationCanceledError error enum is returned instead of QNetworkReply::TimeoutError. What is wrong? Am i doing something wrong or is it Qt bug?
From documentation that error should be if "the operation was canceled via calls to abort() or close() before it was finished."
I see no reason for that.
QByteArray encodedData = data.toUtf8();
QUrl url("http://myapi/jsonrpc");
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QNetworkAccessManager manager;
manager.setTransferTimeout(500);
QNetworkReply* reply = manager.post(request, encodedData);
QEventLoop loop;
connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
loop.exec();
if (reply->error() != QNetworkReply::NoError) {
QString errorMsg = QString("HTTP Network request has failed. Code: ") + QVariant::fromValue(reply->error()).toString();
delete reply;
// error
// here i got QNetworkReply::OperationCanceledError
}
QByteArray response = reply->readAll();
//ok

Related

Bearer authentication with Qt (QNetworkAccessManager)

I was trying to perform Bearer authentication for https://developer.olx.ua/api/doc#tag/Adverts/paths/~1adverts/get from my Qt app. I use QNetworkAccessManager. But I couldn't find any help on this.
I try this code
QNetworkAccessManager *manager = new QNetworkAccessManager;
QEventLoop loop;
QObject::connect(manager, &QNetworkAccessManager::finished, &loop,
&QEventLoop::quit);
const QUrl url("https://www.olx.ua/api/partner/threads");
QNetworkRequest request {url};
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
QString temp = "Bearer " + marketplaceAccessToken;
request.setRawHeader("Authorization", temp.toLocal8Bit());
request.setRawHeader("Version", "2.0");
QNetworkReply *reply = manager->get(request);
loop.exec();
QByteArray dataReply = reply->readAll();
qDebug() << dataReply;
The server reply is {"error":{"status":400,"title":"Bad Request","detail":"Invalid owner in token"}}
How can I fix it?

QNetworkReply::NetworkError(ProtocolUnknownError)

In my project, I am attempting to download a YouTube profile picture. The YouTube API returns this link https://yt3.ggpht.com/-7ipuUvDjVT8/AAAAAAAAAAI/AAAAAAAAAAA/hSPOcUsb1nw/s240-c-k-no-mo-rj-c0xffffff/photo.jpg
However, using the same function for downloading files from my own website doesn't work with this URL. I get QNetworkReply::NetworkError(ProtocolUnknownError) in the application output.
Here is my code:
QByteArray downloadFileData(QString url)
{
QNetworkRequest request;
request.setUrl(QUrl(url));
QNetworkReply *reply = manager->get(request);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
if(reply->error() == QNetworkReply::NoError)
{
return reply->readAll();
}
else
{
qDebug() << reply->error();
}
reply->deleteLater();
return "";
}
When I pass that url to this function, I get that error. What is going on?
Thanks for your time

QNetworkAccessManager does not emit signal

So I have this code:
QUrl url("http://...");
QNetworkRequest request(url);
QNetworkReply *reply = m_networkManager->get(request);
connect(reply, SIGNAL(finished()), SLOT(onRequestCompleted()));
connect(reply,SIGNAL(error(QNetworkReply::NetworkError)),SLOT(onError(QNetworkReply::NetworkError)));
and I cant get signal to the other fuction
void IpResolver::onRequestCompleted()
{
QString webContent;
QNetworkReply *reply = qobject_cast<QNetworkReply*>(sender());
if (reply)
{
if (reply->error() == QNetworkReply::NoError)
{
QString webContent = reply->readAll();
}
}
}
I cant figure out the solution, help please.
I don't know what exactly you want, but:
Why do you use reply pointer instead of some kind onRequestCompleted(QNetworkReply *reply)?
If you do so:
QUrl url("http://...");
QNetworkRequest request(url);
connect(m_networkManager, &QNetworkAccessManager::finished, this, &IpResolver::onRequestCompleted);
m_networkManager->get(request);
And your slot will be, for example:
void IpResolver::onRequestCompleted(QNetworkReply *reply)
{
QString webContent;
if (reply->error() == QNetworkReply::NoError)
webContent = reply->readAll();
}

Getting a page content with Qt

I am trying to get the content of a HTTP request into a QString variable with Qt and C++
QNetworkAccessManager networkManager;
QUrl url("https://someurl.test.com/this-actually-exists");
QNetworkRequest request;
request.setUrl(url);
QNetworkReply* currentReply = networkManager.get(request); // GET
QString reply = QTextCodec::codecForMib(1015)->toUnicode(currentReply->readAll());
Still, the variable reply seems to stay empty. Obviously, I misunderstand the documentation. How do I get this to perform?
You can use two different ways even the synchronous or asynchronous ways to do this. The asynchronous way is :
connect (&networkManager , SIGNAL(finished(QNetworkReply*)) ,this, SLOT(done(QNetworkReply*)));
networkManager.get(request);
And you should read the contents from the returned reply in the slot connected to finished signal in the following way :
void net::done(QNetworkReply * reply)
{
if (reply->error() == QNetworkReply::NoError)
{
data = QString(reply->readAll ());
}
else
{
data = QString(reply->errorString ());
}
}
The synchronous way is like :
QNetworkReply *reply = networkManager.get(request);
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), &loop, SLOT(quit()));
loop.exec();
QByteArray bts = reply->readAll();
QString str(bts);
Here you use an event loop to wait until the reply is finished and then read the available bytes and get the string.
I need to assume you're running an application with an event-loop in place? If not, then it's a bit harder...
If so, replace your last line that builds the reply QString:
connect(currentReply, SIGNAL(finished()), this, SLOT(gotAReply()));
Then you'll have to define another method in your class as a slot that gets triggered as soon as that reply got filled:
void gotAReply()
{
QNetworkReply *reply = qobject_cast<QNetworkReply*>(QObject::sender());
if (reply)
{
if (reply->error() == QNetworkReply::NoError)
{
QString replyText( reply->readAll() );
}
reply->deleteLater();
}
}
Don't forget: for Signals and Slot to work your class declaration must contain the Q_OBJECT macro.

How can I use Qt to get html code of the redirected page?

I'm trying to use Qt to download the html code from the following url:
http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?db=nucleotide&cmd=search&term=AB100362
this url will re-direct to
www.ncbi.nlm.nih.gov/nuccore/27884304
I try to do it by following way, but I cannot get anything.
it works for some webpage such as www.google.com, but not for this NCBI page. is there any way to get this page??
QNetworkReply::NetworkError downloadURL(const QUrl &url, QByteArray &data)
{
QNetworkAccessManager manager;
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
if (reply->error() != QNetworkReply::NoError)
{
return reply->error();
}
data = reply->readAll();
delete reply;
return QNetworkReply::NoError;
}
void GetGi()
{
int pos;
QString sGetFromURL = "http://www.ncbi.nlm.nih.gov/entrez/query.fcgi";
QUrl url(sGetFromURL);
url.addQueryItem("db", "nucleotide");
url.addQueryItem("cmd", "search");
url.addQueryItem("term", "AB100362");
QByteArray InfoNCBI;
int errorCode = downloadURL(url, InfoNCBI);
if (errorCode != 0 )
{
QMessageBox::about(0,tr("Internet Error "), tr("Internet Error %1: Failed to connect to NCBI.\t\nPlease check your internect connection.").arg(errorCode));
return "ERROR";
}
}
That page appears to have a redirect.
From the Qt docs for 4.6:
Note: When the HTTP protocol returns a
redirect no error will be reported.
You can check if there is a redirect
with the
QNetworkRequest::RedirectionTargetAttribute
attribute.