0

Je vérifie la compatibilité de mon code avec les codes d'état HTTP 3xx (redirections).QNetworkAccessManager ne gère pas le code d'état HTTP 308

Je suis intéressé par les codes 301, 302, 303, 307 et 308.

Tous ceux qui travaillent très bien avec mon code, à l'exception 308.

Mon testcase client est Qt/C++ base, et mon serveur de test est basé sur python. Je posterai le code des deux.

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

je lance le serveur, alors qu'il est en cours d'exécution, je lance le client et je reçois got 0 bytes dans le console. Si je change la réponse de 308 à, disons, 301, cela fonctionne bien (imprime got 3 bytes).

Une idée pourquoi?

Remarque: La redirection fonctionne correctement dans Chrome, mon code serveur est probablement correct.

Remarque: Il semble qu'il soit documenté comme non pris en charge. De the docs:

Ce signal est émis si le QNetworkRequest :: FollowRedirectsAttribute a été fixé dans la requête et le serveur a répondu avec un statut 3xx (spécifiquement 301, 302, 303, 305 ou 307 code d'état) avec url valide dans l'en-tête de l'emplacement, indiquant une redirection HTTP.

(Souligné par l'auteur)

Je voudrais encore savoir pourquoi , cependant.

+0

Probablement parce que 308 est expérimental. Je ne crois pas que ce soit dans une norme officielle pour le moment. – jszakmeister

Répondre

0

Pour toute personne qui a le même problème, voici ma classe FileDownloader avec le soutien de 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