2013-02-11 2 views
5

J'ai un webviewer et je veux seulement que ce soit seulement en mesure d'accéder à nos webapps, pour y parvenir, j'ai placé un en-tête php que je cherche dans mon application Qt. Cela fonctionne bien, mais avec une exception et avec 301 codes d'état déplacés permanents. Les navigateurs modernes vous redirigent automatiquement mais en mettant un "/" à la fin de la requête http. Lorsqu'une URL de notre application Web est entrée, elle doit actuellement être marquée par un slash pour pouvoir détecter les en-têtes, mais je souhaite qu'elle obtienne également cette en-tête, même si elle ne place pas de barre oblique.QNetworkReply et 301 redirection

Voici ma méthode actuelle pour récupérer l'en-tête:

QNetworkAccessManager *manager = new QNetworkAccessManager(this); 
    QNetworkRequest request; 
    request.setUrl(url); 
    connect(manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(onFinished(QNetworkReply*))); 

    request.setRawHeader("User-Agent", "CytoViewer 1.0"); 
    request.setHeader(QNetworkRequest::ContentTypeHeader,"application/CytoViewer"); 
    QNetworkReply *reply = manager->get(request); 
    reply->ignoreSslErrors(); 
    QEventLoop loop; 

    connect(reply, SIGNAL(finished()), &loop, SLOT(quit())); 
    loop.exec(); 
    qDebug() << "QLoop reply all: " << reply->readAll(); 
    qDebug() << "QLoop: " << reply->rawHeader("Cyto-Study-Manager"); 
    if(reply->rawHeader("OurWebApp") == "1"){ 
     //Header exists?(QEventLoop finish) Set arg[1]"url 'Found prouct: product header'" 
     product = reply->rawHeader("Product"); 
     return true; 
    } else { 
     //Header doen't exist? Graceful error - not a valid PI product 
     return false; 
    } 

Pour résoudre le problème de de frapper un 301 d'abord j'envoyer deux demandes de réseau, la première touche l'URL saisie et vérifiez pour une 301 si il y a un code d'état 301 il obtient l'url proposé via la méthode reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); et retourne cette URL sinon s'il n'y a pas de code d'état puis il retourne simplement l'URL précédente que l'utilisateur a saisie et envoie ensuite une autre requête réseau pour vérifier les en-têtes.

demande d'abord j'envoyer à vérifier le code d'état:

QUrl MainWindow::networkRequest(QUrl checkUrl){ 
    qDebug() << "checkURL: " << checkUrl; 
    // 
    QNetworkAccessManager *manager = new QNetworkAccessManager(this); 
    QNetworkRequest request; 
    request.setUrl(checkUrl); 
    request.setRawHeader("User-Agent", "CytoViewer 1.0"); 
    request.setHeader(QNetworkRequest::ContentTypeHeader,"application/CytoViewer"); 
    QNetworkReply *reply = manager->get(request); 
    reply->ignoreSslErrors(); 
    QEventLoop checkLoop; 
    connect(reply, SIGNAL(finished()), &checkLoop, SLOT(quit())); 
    checkLoop.exec(); 
    //Check status code 
    if (reply->error() == QNetworkReply::NoError) { 
     int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); 
     if(statusCode == 301) { 
      QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); 
      return redirectUrl; 
     }else { 
      return checkUrl; 
     } 

    } 
} 

Longue histoire courte, je vous envoie deux demandes de réseau, 1) Pour vérifier 301 2) Pour vérifier notre tête d'application.

Est-il possible de le faire en une seule fois? Ai-je manqué une méthode qui effectuera cette redirection automatiquement?

Cordialement

Nathan

Répondre

9

Apparemment, il n'y a pas.

Il y a une entrée de HOWTO officiel sur http://developer.nokia.com/community/wiki/Handling_an_HTTP_redirect_with_QNetworkAccessManager (lien mort, malheureusement)

Extraction de lien ci-dessus:

void QNAMRedirect::replyFinished(QNetworkReply* reply) { 
    /* 
    * Reply is finished! 
    * We'll ask for the reply about the Redirection attribute 
    * http://doc.trolltech.com/qnetworkrequest.html#Attribute-enum 
    */ 
    QVariant possibleRedirectUrl = 
      reply->attribute(QNetworkRequest::RedirectionTargetAttribute); 

    /* We'll deduct if the redirection is valid in the redirectUrl function */ 
    _urlRedirectedTo = this->redirectUrl(possibleRedirectUrl.toUrl(), 
             _urlRedirectedTo); 

    /* If the URL is not empty, we're being redirected. */ 
    if(!_urlRedirectedTo.isEmpty()) { 
     QString text = QString("QNAMRedirect::replyFinished: Redirected to ") 
           .append(_urlRedirectedTo.toString()); 
     this->_textContainer->setText(text); 

     /* We'll do another request to the redirection url. */ 
     this->_qnam->get(QNetworkRequest(_urlRedirectedTo)); 
    } 
    else { 
     /* 
     * We weren't redirected anymore 
     * so we arrived to the final destination... 
     */ 
     QString text = QString("QNAMRedirect::replyFinished: Arrived to ") 
           .append(reply->url().toString()); 
     this->_textContainer->setText(text); 
     /* ...so this can be cleared. */ 
     _urlRedirectedTo.clear(); 
    } 
    /* Clean up. */ 
    reply->deleteLater(); 
} 

QUrl QNAMRedirect::redirectUrl(const QUrl& possibleRedirectUrl, 
           const QUrl& oldRedirectUrl) const { 
    QUrl redirectUrl; 
    /* 
    * Check if the URL is empty and 
    * that we aren't being fooled into a infinite redirect loop. 
    * We could also keep track of how many redirects we have been to 
    * and set a limit to it, but we'll leave that to you. 
    */ 
    if(!possibleRedirectUrl.isEmpty() && 
     possibleRedirectUrl != oldRedirectUrl) { 
     redirectUrl = possibleRedirectUrl; 
    } 
    return redirectUrl; 
} 
+0

Je pensais qu'il n'y avait peut-être pas moyen mais je ne savais pas si quelque chose me manquait quelque part, merci d'effacer @kfunk :) – Kal

+1

le lien vers le HOWTO officiel est cassé :( –

+0

@ DavidSánchez: Mis à jour le commentaire Malheureusement, le contenu du wiki n'a pas été déplacé avant sa suppression :( – kfunk

14

C'est un peu vieux, mais le soutien de redirection automatique est simplement ajouté à Qt 5.6. Vérifiez cela sur QNetworkRequest::FollowRedirectsAttribute (http://doc.qt.io/qt-5/qnetworkrequest.html).

+1

Que voulez-vous dire vieux? Pour moi, c'est nouveau.Merci de mentionner cela, vous avez enregistré mon **, je vais mettre à jour de 5.5 à 5.6 pour que cela fonctionne. –