QNetworkAccessManager doesn't handle HTTP Status Code 308

不打扰是莪最后的温柔 提交于 2019-12-25 10:08:20

问题


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

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

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

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

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

Any idea why?

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:

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.

(emphasis mine)

I'd still like to know why, though.


回答1:


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:

#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


来源:https://stackoverflow.com/questions/46100802/qnetworkaccessmanager-doesnt-handle-http-status-code-308

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!