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
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.
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"));
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()));
}
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());
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;
});
}