[英]QNetworkReply and 301 redirect
我有一個 webviewer,只希望它只能訪問我們的 webapps,為了實現這一點,我在 Qt 應用程序中放置了一個 php 頭文件。 這工作正常,但有一個例外,那就是 301 永久移動狀態代碼。 現代瀏覽器會自動重定向您,但會在 http 請求的末尾放置一個“/”。
當輸入我們的網絡應用程序的 URL 時,它當前需要尾部斜杠才能檢測標題,但我希望它也能獲取該標題,即使他們沒有放置尾部斜杠。
這是我當前檢索標題的方法:
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;
}
為了解決首先點擊 301 的問題,我發送了兩個網絡請求,第一個點擊輸入的 URL 並檢查 301 是否有 301 狀態代碼,它通過reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
方法並返回該 URL,否則如果沒有狀態代碼,則它僅返回用戶輸入的先前 URL,然后發送另一個網絡請求以檢查標頭。
我發出的第一個請求是檢查狀態代碼:
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;
}
}
}
長話短說,我發送了兩個網絡請求,1)檢查 301 2)檢查我們的應用程序標頭。
有沒有辦法在一個請求中做到這一點? 我是否缺少一種可以自動執行此重定向的方法?
問候
彌敦道
如果您使用的是 Qt 6,則跳過閱讀此答案,因為自動重定向是默認行為
如果您不使用 Qt 6,則舊答案:
Qt 5.6 ( QNetworkRequest::FollowRedirectsAttribute
) 中添加了自動重定向支持。
默認情況下未啟用:
QNetworkRequest req(QUrl("https://example.com/"));
req.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true);
顯然沒有。
http://developer.nokia.com/community/wiki/Handling_an_HTTP_redirect_with_QNetworkAccessManager上有一個官方 HOWTO 條目(不幸的是,死鏈接)
從上面的鏈接中提取:
void QNAMRedirect::replyFinished(QNetworkReply* reply) {
/*
* Reply is finished!
* We'll ask for the reply about the Redirection attribute
* http://doc.trolltech.com/qnetworkrequest.html#Attribute-enum
*/
QVariant possibleRedirectUrl =
reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
/* We'll deduct if the redirection is valid in the redirectUrl function */
_urlRedirectedTo = this->redirectUrl(possibleRedirectUrl.toUrl(),
_urlRedirectedTo);
/* If the URL is not empty, we're being redirected. */
if(!_urlRedirectedTo.isEmpty()) {
QString text = QString("QNAMRedirect::replyFinished: Redirected to ")
.append(_urlRedirectedTo.toString());
this->_textContainer->setText(text);
/* We'll do another request to the redirection url. */
this->_qnam->get(QNetworkRequest(_urlRedirectedTo));
}
else {
/*
* We weren't redirected anymore
* so we arrived to the final destination...
*/
QString text = QString("QNAMRedirect::replyFinished: Arrived to ")
.append(reply->url().toString());
this->_textContainer->setText(text);
/* ...so this can be cleared. */
_urlRedirectedTo.clear();
}
/* Clean up. */
reply->deleteLater();
}
QUrl QNAMRedirect::redirectUrl(const QUrl& possibleRedirectUrl,
const QUrl& oldRedirectUrl) const {
QUrl redirectUrl;
/*
* Check if the URL is empty and
* that we aren't being fooled into a infinite redirect loop.
* We could also keep track of how many redirects we have been to
* and set a limit to it, but we'll leave that to you.
*/
if(!possibleRedirectUrl.isEmpty() &&
possibleRedirectUrl != oldRedirectUrl) {
redirectUrl = possibleRedirectUrl;
}
return redirectUrl;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.