QNetworkRequest URL containing '?' - not requesting properly because of QUrl encoding - c++

I have the next code to make a request:
void HTTPClient::post(QString connectionString, QHttpMultiPart* _multiPart, bool returnProgress) {
QUrl url;
if (ssl)
url.setScheme("https");
else
url.setScheme("http");
url.setHost(host);
url.setPort(port);
url.setPath(connectionString);
url.setUrl(url.toEncoded());
QNetworkRequest request(url);
request.setRawHeader("User-Agent", QCoreApplication::applicationName().toLatin1());
/*...irrelevant code...*/
}
The requested url should be
https://somewebpage.domain:443/REST/login.php?method=login_md5
but the QNetworkRequest requests this one despite I set the url as encoded (debugging url.toEncoded() prints the '?' correctly):
https://somewebpage.domain:443/REST/login.php%3Fmethod=login_md5
This results in a 404 not found page. I have tried setting the url with url.toString() and just url, but the '?' keeps messing up. What can I do to request the link properly?
I have tried building the QUrl in the constructor like this:
QUrl url("https://"+host+port+connectionString);
But results in the next string:
https://somewebpage.xn--domain-efa/REST/login.php?method=login_md5

You can try QUrl::fromEncoded
url.setUrl( QUrl::fromPercentEncoding(url.toEncoded()));
Parses input and returns the corresponding QUrl. input is assumed to
be in encoded form, containing only ASCII characters.
to correctly handle characters.

The encoded URL seems valid, maybe a problem with your webserver?

You can setPath() and setQuery() separatly. What come before the '?' is the path and after is the query arguments.
const QStringList path_part = path.split('?');
url.setPath(path_part.at(0));
if(path_part.size() > 1)
url.setQuery(path_part.at(1));

Related

QUrlQuery append?

Is it possible to use QUrlQuery to append data without striping the url?
Using the code bellow will strip everything after the "?" and
the result is:
https://foobar.com/Info.xml.aspx?userdata=1234
I would like to get:
https://foobar.com/Info.xml.aspx?user=jack&userdata=1234
QUrl url("https://foobar.com/Info.xml.aspx?user=jack&");
QString data = "1234";
QUrlQuery query;
query.addQueryItem("userdata", data);
url.setQuery(query);
I'm asking because i need to make multiple calls, every time adding a new parameter and "building" the url from scratch every time is annoying.
You have to get the query and then add the item:
QUrl url("https://foobar.com/Info.xml.aspx?user=jack&");
QString data = "1234";
QUrlQuery query(url.query());
query.addQueryItem("userdata", data);
url.setQuery(query);
qDebug()<<url;
Output:
QUrl("https://foobar.com/Info.xml.aspx?user=jack&userdata=1234")

Add dynamic variables to an url

I would like to add dynamic variables to an url example:
QNetworkRequest req( QUrl( QString("http://website.com/?test=1&id=1") ) );
But when i try this:
// the HTTP request
varUrl = "http://website.com/?test=";
varUrl += info;
varUrl += "&id=";
varUrl += info_2;
QNetworkRequest req( QUrl( QString(varUrl) ) );
QNetworkReply *reply = mgr.get(req);
eventLoop.exec(); // blocks stack until "finished()" has been called
i get this error:
The error message you posted is partly unrelated. Your actual problem is this:
QNetworkRequest req( QUrl( QString(varUrl) ) );
This is treated as a function declaration. This is a corner case in C++ and it's commonly referred to as the "most vexing parse". See https://en.wikipedia.org/wiki/Most_vexing_parse for an explanation.
In any event, use the QUrl::fromUserInput() static function instead of passing the query string directly. This will encode the query correctly (otherwise you'd need to manually encode the query correctly by hand.) So in short, change the above line to:
QNetworkRequest req(QUrl::fromUserInput(varUrl));
This also fixes the parsing issue; the above is treated correctly like a variable definition, not a function declaration, and your code should now compile fine.
As a side-note, you can use the QString::arg() function to construct your string in one go, without having to use append (+=) operations. So you can construct your URL string like this:
varUrl = QString("http://website.com/?test=%1&id=%2").arg(info).arg(info_2);
%1 will be replaced with the contents of info, and %2 with the contents of info_2.
According to the documentation:
The QUrlQuery class provides a way to manipulate a key-value pairs in
a URL's query.
It is used to parse the query strings found in URLs like the
following:
Posible solution is to use QUrlQuery:
QString info = "1";
QString info_2 = "1";
QUrl url("http://website.com/");
QUrlQuery query;
query.addQueryItem("test", info);
query.addQueryItem("id", info_2);
url.setQuery(query);

Qt QUrlQuery param split

I use the Qt v5.5. I need http get a request like this
QUrlQuery urlQuery;
urlQuery.setQuery("https://lalala.com/login");
urlQuery.addQueryItem("submit", "");
urlQuery.addQueryItem("email", "email#email.com");
urlQuery.addQueryItem("pass", "unbelievable_password");
when I call urlQuery.query(); the url is
"https://lalala.com/login&submit=&email=email#email.com&pass=unbelievable_password"
the param "submit" is the first param, it need use '?' split the param name, but the param is split by '&'.
You want to get the URL into a QUrl, then add query items on that -- and not have the URL as a query item itself!
QUrl url("https://www.foo.com");
QUrlQuery query;
query.addQueryItem("email", "foo#bar.com");
query.addQueryItem("pass", "secret");
url.setQuery(query);
qDebug() << url;
Correctly prints
QUrl("https://www.foo.com?email=foo#bar.com&pass=secret")
Looks like there's been discussion here on SO already. In general it looks as though any "sub-delims" should be accepted with or without a value: https://www.rfc-editor.org/rfc/rfc3986#appendix-A
Truth is, it's too bad that the QUrlQuery doesn't have the option for a value-less query without a trailing equal sign

C++ - QWebView Formatting Url as (string,QUrl)

I am trying to set QwebView's Url as "http://" and other part of url entered from linedit. Here's my function:
void MainWindow::on_git_clicked()
{
QUrl adrs;
adrs=ui->lineEdit->text();
ui->webView->setUrl(QUrl("http://" + adrs);
}
But it does nothing. But it was working on Python with same way. Thanks for help.
How about this, since your using QUrl and trying to append it to "http://" why not just use a QString instead? this might be your problem
QString adrs(ui->lineEdit->text());
ui->webview->setURL(QUrl("http://" + adrs));

QNetworkAccessManager problem

I'm trying to open a web page using QNetworkAccessManager - and for some pages it works fine - while for others it does not. I tried setting a real browser user-agent, however it still doesn't work for example, http://www.erepublik.com. Here's the code:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
connect(manager, SIGNAL(finished(QNetworkReply*)),
this, SLOT(replyFinished(QNetworkReply*)));
QNetworkRequest *request = new QNetworkRequest(QUrl("http://www.erepublik.com"));
request->setRawHeader( "User-Agent", "Mozilla/5.0 (X11; U; Linux i686 (x86_64); "
"en-US; rv:1.9.0.1) Gecko/2008070206 Firefox/3.0.1" );
request->setRawHeader( "charset", "utf-8" );
request->setRawHeader( "Connection", "keep-alive" );
manager->get(*request);
...
void MainWindow::replyFinished(QNetworkReply *reply)
{
QString data = reply->readAll();
qDebug() << data;
}
The data is the following:
<html><head><meta http-equiv="refresh" content="0;url=http://www.erepublik.com/en"/></head></html><html><head><meta http-equiv="refresh" content="0;url=http://www.erepublik.com/en"/></head></html>
Now, what's bugging me this works for a site like http://www.hardwarebase.net (data returns the normal HTML source), while it doesn't work for eRepublik.
For those who are curious to know what I exactly want to do - I want to get the population number of countries from the eRepublik front page.
Any ideas why is this happening? Thanks in advance.
It looks like you're getting the data correctly, it's just that that particular URL just forwards you to a different one. Try http://www.erepublik.com/en (with the /en) instead.
The returned HTML is re-directing you to http://www.erepublik.com/en so you would be best off forming you QNetworkRequest to go straight to that URL.