PDA

View Full Version : QT4 HTTP Example and Redirecting



jiveaxe
1st June 2008, 16:59
Hi,
I was trying the HTTP Example of qt4 documentation and noticed that it can't manage itself the status code 302, it can't perform a redirection.

An example is this link:
http://next.videogame.it/img/articoli/4500/4905/projectsnowblind_recensione.cover.T5.jpg

With the line below I get the new url:


QString newLocation = responseHeader.value("Location");

But I don't know how to use it.

Have anybody some tips for me?

Thanks

EDITED: HTTP Example (http://doc.trolltech.com/4.4/network-http.html)

wysota
2nd June 2008, 07:22
When you receive the new location simply change the url of the request to the one you received in the location header and resubmit the request.

profoX
2nd June 2008, 13:50
I had the same problem sometime ago.
I solved it like this:


self.connect(self.http, SIGNAL("responseHeaderReceived(const QHttpResponseHeader &)"), self.handleHeaderResponse)

[...]

def handleHeaderResponse(self, resp):
code = resp.statusCode()
if (code >= 300 and code < 400 and resp.hasKey("location")):
location = QUrl(resp.value("location"))
self.http.setHost(location.host())
self.http.get(location.toString())

As you can see it's copied from my PyQt4 application... In C++ it should be something like this (not tested!)


connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), this, SLOT(handleHeaderResponse(const QHttpResponseHeader &)));

[...]

void MyClass::handleHeaderResponse(const QHttpResponseHeader &resp):
int code = resp.statusCode();
if (code >= 300 and code < 400 and resp.hasKey("location")) {
QUrl location = QUrl(resp.value("location"));
http.setHost(location.host());
http.get(location.toString());
}

Hope it helps you!

jiveaxe
4th June 2008, 16:42
I'm trying different ways but with no luck.

First of all the code:


class InternetJob: public QObject
{
Q_OBJECT

public:
InternetJob(const QString &u);
QByteArray getData(){return data;}
int getStatusCode(){return statusCode;}
QString getLocation(){return location;}
bool isRequestAborted(){return httpRequestAborted;}
bool isRedirecting(){return needRedirect;}
void download();

private slots:
void httpRequestFinished(int requestId, bool error);
void readResponseHeader(const QHttpResponseHeader &responseHeader);

signals:
void requestFinished();

private:
QHttp *http;
QUrl url;
bool httpRequestAborted;
int httpGetId;
QByteArray data;
int statusCode;
QString location;
};

InternetJob::InternetJob(const QString &u)
: url(u)
{
http = new QHttp;
connect(http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)), this, SLOT(readResponseHeader(const QHttpResponseHeader &)));
connect(http, SIGNAL(requestFinished(int, bool)), this, SLOT(httpRequestFinished(int, bool)));

download();
}

void InternetJob::download()
{
QString query;
for(int i = 0; i < url.queryItems().size(); ) {
query += url.queryItems().at(i).first + "=" + url.queryItems().at(i).second;
if(++i < url.queryItems().size())
query += "&";
}

QHttpRequestHeader header;
if(url.queryItems().size() > 0)
header.setRequest("GET", url.path() + "?" + QUrl::toPercentEncoding(query,"&="));
else
header.setRequest("GET", url.path());
header.setValue("Host", url.host());

httpRequestAborted = false;
http->setHost(url.host());
httpGetId = http->request(header);
qDebug() << "job id = " << httpGetId;
}

void InternetJob::readResponseHeader(const QHttpResponseHeader &responseHeader)
{
statusCode = responseHeader.statusCode();
QRegExp rx("\?$");

switch(statusCode) {
case 200:
case 301:
case 303:
case 307:
break;

case 302:
location = responseHeader.value("Location");
// Remove trailing "?"
location.remove(rx.indexIn(location), 1);
httpRequestAborted = true;
http->abort();
break;

default:
qDebug() << QString(trUtf8("Download failed: %1.").arg(responseHeader.reasonPhrase()));
httpRequestAborted = true;
http->abort();
}
}

void InternetJob::httpRequestFinished(int requestId, bool error)
{
if (requestId != httpGetId)
return;
qDebug() << "job finished = " << requestId;
if (httpRequestAborted) {
qDebug() << "Request Aborted. Status Code: " << statusCode;
if(statusCode == 302) {
url.setUrl(location);
download();
return;
}
else {
emit requestFinished();
return;
}
}

if(error)
qDebug() << QString(trUtf8("Download failed: %1.").arg(http->errorString()));
else
data = http->readAll();
emit requestFinished();
}

The code above works well until the http status code is 200; if the status code is 302 it starts a new http->request(...) but after it neither responseHeaderReceived nor httpRequestFinished signals are emitted.

Where is my mistake?

Thanks