QNetworkAccessManager не обрабатывает код состояния HTTP 308
Я проверяю свой код на совместимость с кодами состояния 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 работает нормально, поэтому код моего сервера, скорее всего, правильный.
Примечание. Похоже, что оно задокументировано как неподдерживаемое. Из документов:
Этот сигнал испускается, если в запросе был установлен QNetworkRequest::FollowRedirectsAttribute, и сервер ответил статусом 3xx (в частности, кодом статуса 301, 302, 303, 305 или 307) с действительным URL-адресом в заголовке местоположения, что указывает на перенаправление HTTP,
(акцент мой)
Я все еще хотел бы знать почему, хотя.
1 ответ
Для тех, у кого такая же проблема, вот мой класс 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