QNetworkAccessManager不处理HTTP状态代码308 [英] QNetworkAccessManager doesn't handle HTTP Status Code 308

查看:1103
本文介绍了QNetworkAccessManager不处理HTTP状态代码308的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm testing my code for compatibility with HTTP 3xx status codes (redirects).

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

I'm interested in codes 301, 302, 303, 307 and 308.

所有这些都适用于我的代码,但308除外。

All of those work fine with my code, except 308.

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

My client testcase is Qt/C++ based, and my testing server is python-based. I'll post the code of both.

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()

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

I run the server, then while it's running, I run the client and I get got 0 bytes in the console. If I change the response from 308 to, say, 301, it works fine (prints got 3 bytes).

知道为什么吗?

注意: Chrome中的重定向工作正常,因此我的服务器代码可能是正确的。

Note: The redirect works fine in Chrome, so my server code is likely correct.

注意:好像它被记录为不受支持。来自文档

Note: It seems like it's documented as unsupported. From the docs:


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

This signal is emitted if the QNetworkRequest::FollowRedirectsAttribute was set in the request and the server responded with a 3xx status (specifically 301, 302, 303, 305 or 307 status code) with a valid url in the location header, indicating a HTTP redirect.

(强调我的)

我仍然想知道为什么

推荐答案

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

For anyone who has the same problem, here's my FileDownloader class with support for 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:

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

这篇关于QNetworkAccessManager不处理HTTP状态代码308的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆