QNetworkReply和301重定向

12
我有一个WebViewer,只想让它能够访问我们的Web应用程序。为了实现这一点,我已经放置了一个PHP头文件,并在我的Qt App中查找它。这个方法很好用,但有一个例外,就是301永久移动状态代码。现代浏览器会自动重定向,但在HTTP请求末尾加上“/”。

当输入我们Web应用程序的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;否则,如果没有状态码,则简单地返回用户输入的上一个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)检查我们的应用程序头文件。
有没有办法在一个请求中完成这个操作?我是否错过了一个可以自动重定向的方法?
问候,
Nathan
2个回答

28

2
你说的“旧”是什么意思?对我来说它是新的。谢谢你提醒,你救了我一命,我会升级到5.6版本以使其正常工作。 - Raiden Core
1
快速更新:QNetworkRequest::FollowRedirectsAttribute已被弃用,建议使用QNetworkRequest::RedirectPolicyAttribute(请查看可能的值)。 - cbuchart
我正在使用Qt6,但默认情况下似乎没有重定向,因为它没有起作用。 - HBatalha
@HBatalha 嗯,奇怪,你确定它不是试图从https重定向到http吗? - Konrad
@Konrad,是的,这里是链接,你可以测试:https://www.dropbox.com/s/zqbxgw4owoteas0/version.txt?dl=1 - HBatalha

12
显然没有。
这里有一篇官方的HOWTO入门文章,介绍如何使用QNetworkAccessManager处理HTTP重定向:https://web.archive.org/web/20141101060340/http://developer.nokia.com/community/wiki/Handling_an_HTTP_redirect_with_QNetworkAccessManager 以下是上述链接中的摘录:
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;
}

我曾经认为可能没有办法,但不确定是否有什么地方我错过了什么,感谢@kfunk的澄清 :) - Kal
1
官方HOWTO的链接已经失效了:( - David Sánchez
@DavidSánchez:已更新评论以反映此事。不幸的是,在其被删除之前,维基内容尚未移动 :( - kfunk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接