【问题标题】:QNetworkAccessManager doesn't handle HTTP Status Code 308QNetworkAccessManager 不处理 HTTP 状态码 308
【发布时间】:2018-02-16 10:54:58
【问题描述】:

我正在测试我的代码与 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)。

知道为什么吗?

注意:重定向在 Chrome 中运行良好,因此我的服务器代码可能是正确的。

注意:它似乎被记录为不受支持。来自the docs

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

(强调我的)

不过,我仍然想知道为什么

【问题讨论】:

  • 可能是因为 308 是实验性的。我认为它还没有成为官方标准。

标签: qt http networking http-status-codes http-status-code-308


【解决方案1】:

对于遇到同样问题的任何人,这是我的支持 308 的 FileDownloader 类。

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);
}

文件下载器.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

【讨论】:

    猜你喜欢
    • 2012-12-18
    • 2020-07-14
    • 2022-06-21
    • 2017-06-27
    • 2019-09-18
    • 1970-01-01
    • 2019-08-26
    • 1970-01-01
    • 2022-11-10
    相关资源
    最近更新 更多