I have a webviewer and only want it to only be able to access our webapps, to achieve this I have placed a php header which I look for in my Qt App. This works fine but with one exception and that's with 301 permanent moved status codes. Modern browsers redirect you automatically but putting a "/" at the end of the http request.
When a URL to our web app is entered it currently needs the trailing slash to be able to detect the headers but I want it to also get at that header even if they don't put a trailing slash.
Here is my current method to retrieve the header:
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkRequest request;
request.setUrl(url);
connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*)));
request.setRawHeader("User-Agent", "CytoViewer 1.0");
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/CytoViewer");
QNetworkReply *reply = manager->get(request);
reply->ignoreSslErrors();
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
qDebug() << "QLoop reply all: " << reply->readAll();
qDebug() << "QLoop: " << reply->rawHeader("Cyto-Study-Manager");
if(reply->rawHeader("OurWebApp") == "1"){
//Header exists?(QEventLoop finish) Set arg[1]"url 'Found prouct: product header'"
product = reply->rawHeader("Product");
return true;
} else {
//Header doen't exist? Graceful error - not a valid PI product
return false;
}
To solve the problem of of hitting a 301 first I send two network requests, The first one hits the URL entered and check for a 301 if there is a 301 status code it get's the proposed url via the reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
method and returns that URL else if there is no status code then it simply returns the previous URL the user entered and then sends another network request to check the headers.
First request I send out to check status code:
QUrl MainWindow::networkRequest(QUrl checkUrl){
qDebug() << "checkURL: " << checkUrl;
//
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
QNetworkRequest request;
request.setUrl(checkUrl);
request.setRawHeader("User-Agent", "CytoViewer 1.0");
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/CytoViewer");
QNetworkReply *reply = manager->get(request);
reply->ignoreSslErrors();
QEventLoop checkLoop;
connect(reply, SIGNAL(finished()), &checkLoop, SLOT(quit()));
checkLoop.exec();
//Check status code
if (reply->error() == QNetworkReply::NoError) {
int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
if(statusCode == 301) {
QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
return redirectUrl;
}else {
return checkUrl;
}
}
}
Long story short, I am sending two network requests, 1) To check for 301 2) To check for our app header.
Is there anyway to do this in one request? Am I missing a method that will do this redirection automatically?
Regards
Nathan
If you are using Qt 6 then skip reading this answer as auto redirection is a default behaviour
Old answer if you are not using Qt 6:
Auto redirection support was added to Qt 5.6 (QNetworkRequest::FollowRedirectsAttribute
).
It's not enabled by default:
QNetworkRequest req(QUrl("https://example.com/"));
req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);