首页 文章

QNetworkAccessManager不处理HTTP状态代码308

提问于
浏览
0

我正在测试我的代码与HTTP 3xx状态代码(重定向)的兼容性 .

我对代码301,302,303,307和308感兴趣 .

所有这些都与我的代码一起使用,除了308 .

我的客户端测试用例是基于Qt / C的,我的测试服务器是基于python的 . 我会发布两者的代码 .

client.cpp:

#include <QGuiApplication>
#include <QObject>
#include <QByteArray>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>

int main(int argc, char *argv[]) {
    QGuiApplication app(argc, argv);

    QNetworkAccessManager webCtrl;
    QObject::connect(&webCtrl, &QNetworkAccessManager::finished, [&](QNetworkReply* reply) {
        if(reply->error() != QNetworkReply::NoError) {
            qDebug() << "got error";
        }
        QByteArray data = reply->readAll();
        qDebug() << "got" << data.length() << "bytes";
    });

    QNetworkRequest request(QUrl("http://localhost:8080/not_working"));
    request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
    webCtrl.get(request);

    return app.exec();
}

test_server.py:

#!/usr/bin/env python

from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import os

class MyHTTPRequestHandler(BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/working':
            self.send_response(200)
            self.send_header('Content-type','text-html')
            self.end_headers()

            self.wfile.write("hey")
        elif self.path == '/not_working':
            self.send_response(308)
            self.send_header('Location','/working')
            self.end_headers()

server_address = ('127.0.0.1', 8080)
httpd = HTTPServer(server_address, MyHTTPRequestHandler)
httpd.serve_forever()

我运行服务器,然后在它运行时,我运行客户端,我在控制台中得到 got 0 bytes . 如果我将响应从308更改为301,它可以正常工作(打印 got 3 bytes ) .

知道为什么吗?

Note: 重定向在Chrome中正常运行,因此我的服务器代码可能正确无误 .

Note: 好像它被记录为不受支持 . 从the docs

如果在请求中设置了QNetworkRequest :: FollowRedirectsAttribute并且服务器以3xx状态(特别是301,302,303,305或307状态代码)响应并且位置标头中包含有效URL,则会发出此信号,指示HTTP重定向 .

(强调我的)

不过,我还是想知道为什么 .

1 回答

  • 0

    对于有同样问题的人,这是我的FileDownloader类,支持308 .

    filedownloader.cpp:

    #include "filedownloader.h"
    
    FileDownloader::FileDownloader(QUrl imageUrl, QObject *parent) :
        QObject(parent)
    {
        m_imageUrl = imageUrl;
    
        connect(
            &m_webCtrl, SIGNAL (finished(QNetworkReply*)),
            this, SLOT (onDownloaded_internal(QNetworkReply*))
            );
    
        QNetworkRequest request(imageUrl);
        request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
        m_webCtrl.get(request);
    }
    
    FileDownloader::~FileDownloader() {
    }
    
    void FileDownloader::onDownloaded_internal(QNetworkReply* reply) {
        if(reply->error() != QNetworkReply::NoError) {
            qDebug() << "error " << reply->error();
            emit error();
            return;
        }
        if(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt() == 308) {
            handleRedirect308(reply);
            return;
        }
        QByteArray data = reply->readAll();
        reply->deleteLater();
        emit downloaded(data);
        deleteLater();
    }
    
    void FileDownloader::handleRedirect308(QNetworkReply *reply) {
        QByteArray header = reply->rawHeader("location");
        QUrl url(QString::fromUtf8(header));
        url = m_imageUrl.resolved(url);
        QNetworkRequest request(url);
        qDebug() << "308 to " << url;
        request.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
        m_webCtrl.get(request);
    }
    

    filedownloader.h:

    #ifndef FILEDOWNLOADER_H
    #define FILEDOWNLOADER_H
    
    #include <QObject>
    #include <QByteArray>
    #include <QNetworkAccessManager>
    #include <QNetworkRequest>
    #include <QNetworkReply>
    
    class FileDownloader : public QObject {
        Q_OBJECT
    public:
        explicit FileDownloader(QUrl imageUrl, QObject *parent = 0);
        virtual ~FileDownloader();
    
    signals:
        void downloaded(QByteArray const& data);
        void error();
    
    private slots:
        void onDownloaded_internal(QNetworkReply* reply);
    
    private:
        void handleRedirect308(QNetworkReply* reply);
    
        QNetworkAccessManager m_webCtrl;
        QUrl m_imageUrl;
    };
    
    #endif // FILEDOWNLOADER_H
    

相关问题