How do I read headers from a QNetworkReply - c++

How can one read headers for example a cookie out of a QNetworkReply?

I just thought to add to the above answer concerning rawHeader
QList<QByteArray> headerList = reply->rawHeaderList();
foreach(QByteArray head, headerList) {
qDebug() << head << ":" << reply->rawHeader(head);
}

Consulting the documentation, there are a few methods related to reading headers: header, rawHeader, rawHeaderList, and rawHeaderPairs. For the specific case of getting a cookie, you can use the header method. It would look something like this:
QNetworkReply *reply;
// somehow give reply a value
QVariant cookieVar = reply.header(QNetworkRequest::CookieHeader);
if (cookieVar.isValid()) {
QList<QNetworkCookie> cookies = cookieVar.value<QList<QNetworkCookie> >();
foreach (QNetworkCookie cookie, cookies) {
// do whatever you want here
}
}
The header method only works for certain HTTP headers, though. In the general case, if there is no QNetworkRequest::KnownHeaders value for the header you want, the rawHeader method is probably the way to go.

I have tried the answer of Evan Shaw, but there is a little mistake.
The QNetworkRequest::CookieHeader need change to QNetworkRequest::SetCookieHeader. Because I found it is Set-Cookie in the header of QNetworkReply other than Cookie.
QNetworkReply *reply;
// somehow give reply a value
QVariant cookieVar = reply.header(QNetworkRequest::SetCookieHeader);
if (cookieVar.isValid()) {
QList<QNetworkCookie> cookies = cookieVar.value<QList<QNetworkCookie> >();
foreach (QNetworkCookie cookie, cookies) {
// do whatever you want here
}
}

Related

HTTP request in C++ for BlackBerry 10

From this webpage, I have code.
When I use "http://httpbin.org/get", everything is OK.
But when I use my own url, for example "http://my-json-server.typicode.com/typicode/demo/db", I'm getting an error:
Unable to retrieve request headers
Where is my fault?
void RequestHeaders::getRequest()
{
//const QUrl url("http://httpbin.org/get"); // OK
const QUrl url("http://my-json-server.typicode.com/typicode/demo/db"); // Not OK
QNetworkRequest request(url);
QNetworkReply* reply = m_networkAccessManager->get(request);
bool ok = connect(reply, SIGNAL(finished()), this, SLOT(onGetReply()));
Q_ASSERT(ok);
Q_UNUSED(ok);
}
void RequestHeaders::onGetReply()
{
QNetworkReply* reply = qobject_cast<QNetworkReply*>(sender());
QString response;
const QByteArray buffer(reply->readAll());
bb::data::JsonDataAccess ja;
const QVariant jsonva = ja.loadFromBuffer(buffer);
const QMap<QString, QVariant> jsonreply = jsonva.toMap();
QMap<QString, QVariant>::const_iterator it = jsonreply.find("headers");
if (it != jsonreply.end()) {
const QMap<QString, QVariant> headers = it.value().toMap();
for (QMap<QString, QVariant>::const_iterator hdrIter = headers.begin();
hdrIter != headers.end(); ++hdrIter) {
if (hdrIter.value().toString().trimmed().isEmpty())
continue;
response += QString::fromLatin1("%1: %2\r\n").arg(hdrIter.key(),
hdrIter.value().toString());
}
}
for (it = jsonreply.begin(); it != jsonreply.end(); it++) {
if (it.value().toString().trimmed().isEmpty())
continue;
response += QString::fromLatin1("%1: %2\r\n").arg(it.key(), it.value().toString());
}
reply->deleteLater();
if (response.trimmed().isEmpty()) {
response = tr("Unable to retrieve request headers");
}
emit complete(response);
}
Your onGetReply handler is parsing the server's HTTP response body as JSON, searching it for a "headers" child field, and if found then extracts that child's own child fields into a local response variable.
http://httpbin.org/get responds with a JSON object containing a "headers" child object that has child fields in it. So your response variable ends up not being empty.
http://my-json-server.typicode.com/typicode/demo/db responds with a JSON object that does not contain any "headers" child. So your response variable is left empty.
You need to either:
fix your server to respond with JSON that actually matches what your code is expecting.
fix your onGetReply() code to handle the JSON that your server is actually sending.

How to add a token when I use the GET method in Qt?

I would like to add a token in my GET request in C++/Qt.
This is my GET / download method :
QNetworkReply* DownloadManager::doDownload(const QUrl &url)
{
QNetworkRequest request(url);
QNetworkReply *reply = m_manager.get(request); // m_manager is a QNetworkAcessManager
return reply;
}
The tokens are sent as part of the request header, so for that case we use the setRawHeader() method:
void QNetworkRequest::setRawHeader(const QByteArray &headerName, const
QByteArray &headerValue)
Sets the header headerName to be of value headerValue. If headerName
corresponds to a known header (see QNetworkRequest::KnownHeaders), the
raw format will be parsed and the corresponding "cooked" header will
be set as well.
In the case of the token we use the following:
request.setRawHeader(QByteArray("Authorization"), QByteArray("Token your_token"));

Read http request-headers (Qt/c++)

I'm trying to read http request-headers that I can log into the log file (using Qt/c++). I'm able to read the response headers using following simple code:
QList<QByteArray> headerList = pReply->rawHeaderList();
foreach(QByteArray head, headerList)
{
qDebug() << head << ":" << pReply->rawHeader(head);
}
pReply->close();
But so far I had no luck with request headers. While looking for the solution I came across
this post: Read complete HTTP request-header; But I didn't really understand how to achieve similar functionality with Qt.
I'm bit lost. How should I go about this?
The rawHeader is actually a QPair of QByteArray. See: RawHeader. You either do a for each with the RawHeader instead of QByteArray or just iterate through the list:
QList<QByteArray> headerList = pReply->rawHeaderList();
for (int i = 0; i < rawHeaderList.count(); ++i) {
qDebug() << head << ":" << pReply->rawHeader(i);
}
pReply->close();
There is no direct method to get headers of request, but you can get header list and iterate over them and save in a QVariantMap. here is a sample code.
auto reqHeaderName = reply->request().rawHeaderList();
QVariantMap reqHeaders;
for (QString header : reqHeaderName)
{
reqHeaders.insert(header, reply->request().rawHeader(header.toUtf8()));
}

Qt check for valid URL

I am trying to create a Qt application which checks if a URL entered by the user into a text edit is valid.
This is what I have so far but it only ever says the URL entered is valid, even when I enter one which is not.
bool checkUrl(const QUrl &url) {
if (!url.isValid()) {
//qDebug(QString("Invalid URL: %1").arg(url.toString()));
return false;
}
return true;
}
void MainWindow::on_pushButton_clicked()
{
QString usertext = ui->plainTextEdit->toPlainText();
QUrl url = QUrl::fromUserInput(usertext);
if (checkUrl(url))
ui->textEdit->setPlainText("Valid URL.");
else
ui->textEdit->setPlainText("Invalid URL.");
}
Also on the qDebug line there is an error:
/home/user/HTML/mainwindow.cpp:32: error: no matching function for call to ‘qDebug(QString)’
Does anyone know what the problem is as it keeps returning true?
You should use qDebug like this:
qDebug() << QString("Invalid URL: %1").arg(url.toString());
also note that QUrl::isValid() does not check syntax of url. You may want to use regular expressions to validate urls.
QUrl::isValid() only basically checks if the character encoding is right. What are you considering a wrong url?
Re qDebug, the form you use basically encapsulates printf, so it doesn't work with QString. You want to do:
qDebug() << QString("Invalid URL: %1").arg(url.toString());

How to use Google Translate API With c++

I'm a beginner in C++ and using Google task API.
How do I write a C++ program that accepts a word, then invokes Google Translate to translate it from English to French, then saves the resulted page to a local file?
For example, if the user inputs "river", the program should invoke Google Translate to translate into French, the resulting page is:
http://translate.google.com/#en|fr|River%0A
This page should be saved.
I read the official documentation through fully: http://code.google.com/apis/language/translate/v2/getting_started.html
but I couldn't understand how to using REST and I'm not familiar with JSON or AJAX.
You cannot use JSON objects straight in C++.
JSON = JavaScript Object Notation
You need to spawn/create something which can parse such objects. For example I've used QNetworkManager in Qt (in C++) to send build javascript and send requests to google APIs. The result would be a JSON object which I had to parse and either display in a browser (which I made in c++) or parse the results into a c++ class and process it differently (do some calculations with it).
If you just need the data, you can request XML instead of JSON and then you can use a standard XML parser to extract the translated word.
EDIT 1:
Google in their example uses:
https://www.googleapis.com/language/translate/v2?key=YOUR-API-KEY&source=en&target=de&q=words+to+translate
This translate from english (en) to german (de). The words to translate are: "words to translate".
Now build an HTTP request in C++ with this URL as the data. Send that with some network manager or sockets and wait for a reply back. Google will give you back data.
I seen this codes below somewhere but I don't remember where, anyway try this:
QString YourClass::translate(QString keyword, QString from, QString to)
{
//Translate URL
QString url = QString("http://translate.google.com/translate_a/t?client=t&text=%0&hl=%1&sl=%2&tl=%1&multires=1&prev=enter&oc=2&ssel=0&tsel=0&uptl=%1&sc=1").arg(keyword).arg(to).arg(from);
QNetworkAccessManager manager;
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
//Get reply from Google
do {
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
} while(!reply->isFinished());
//Convert to string
QString translation(reply->readAll());
reply->close();
//Free memory
delete reply;
//Remove [[[" from the beginning
translation = translation.replace("[[[\"", "");
//Extract final translated string
translation = translation.mid(0, translation.indexOf(",\"") - 1);
return translation;
}
someone advise me to use libcurl, I will try and see.
You need some kind of HTTP library. I second most of what Adrian said, but here's some (incomplete) Qt code which should give you an idea.
namespace {
const QString API_KEY = /* TODO */;
}
MyQObject :: MyQbject ()
: m_manager (new QNetworkAccessManager (this))
{
connect(manager, SIGNAL (finished (QNetworkReply *)),
this, SLOT (reply_finished (QNetworkReply *)));
}
void MyQObject :: fetch_translation (
QString words,
void (*on_receive)(const QString &))
{
// Let's assume asynchronous but non-concurrent requests.
m_on_receive = on_receive;
QString request =
"https://www.googleapis.com/language/translate/v2"
"?key=%1&source=en&target=de&q=%2";
// May want to url-encode 'words' first.
m_manager -> get (QUrl (request .arg (API_KEY) .arg (words));
}
void MyQObject :: reply_finished (QNetworkReply * reply)
{
m_on_receive (reply -> readAll ());
}
// ...
{
my_q_object -> translate ("hello, world", [](const QString & s) {
qWarning () << "translation is: " << s;
});
}