簡體   English   中英

QNetworkReply 和 301 重定向

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM