web-dev-qa-db-fra.com

Android volley pour gérer la redirection

J'ai récemment commencé à utiliser Volley lib de Google pour mes requêtes réseau. Une de mes requêtes reçoit l’erreur 301 pour la redirection; ma question est la suivante: pouvez-vous gérer la redirection automatiquement ou dois-je la gérer manuellement dans parseNetworkError ou utiliser une sorte de RetryPolicyici?

Merci.

26
Niko

Je l'ai corrigé en attrapant le statut HTTP 301 ou 302, en lisant l'URL de redirection et en le configurant pour demander puis en jetant une expection qui déclenche une nouvelle tentative.

Edit: Voici les clés principales de volley-ball que j’ai modifiées:

  • Ajout de la méthode public void setUrl(final String url) pour la classe Request

  • Dans la classe BasicNetwork, vérification de la redirection après // Gestion de la validation du cache, if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY) || statusCode == HttpStatus.SC_MOVED_TEMPORARILY), puis-je lire l'URL de redirection avec responseHeaders.get("location"), appeler setUrl avec un objet request et jeter une erreur

  • Une erreur get est interceptée et il appelle attemptRetryOnException

  • Vous devez également avoir défini RetryPolicy pour la Request (voir DefaultRetryPolicy pour cela).

21
Niko

Remplacez votre URL par celle-ci: url.replace ("http", "https"); 

par exemple: si votre URL ressemble à ceci: " http: //graph.facebook ......." thanit devrait être comme: " https: // graph .Facebook ......."

ça marche pour moi

36
Mucahit

Si vous ne voulez pas modifier la bibliothèque Volley, vous pouvez récupérer la 301 et renvoyer manuellement la demande.

Dans votre classe GsonRequest, implémentez deliverError et créez un nouvel objet Request avec la nouvelle adresse URL de l'en-tête et insérez-le dans la file d'attente des demandes.

Quelque chose comme ça:

@Override
public void deliverError(final VolleyError error) {
    Log.d(TAG, "deliverError");

    final int status = error.networkResponse.statusCode;
    // Handle 30x 
    if(HttpURLConnection.HTTP_MOVED_PERM == status || status == HttpURLConnection.HTTP_MOVED_TEMP || status == HttpURLConnection.HTTP_SEE_OTHER) {
        final String location = error.networkResponse.headers.get("Location");
        Log.d(TAG, "Location: " + location);
        final GsonRequest<T> request = new GsonRequest<T>(method, location, jsonRequest, this.requestContentType, this.clazz, this.ttl, this.listener, this.errorListener);
        // Construct a request clone and change the url to redirect location.
        RequestManager.getRequestQueue().add(request);
    }
}

De cette façon, vous pouvez continuer à mettre à jour Volley sans avoir à vous soucier de la casse.

12
slott

Comme beaucoup d'autres, je ne comprenais tout simplement pas pourquoi Volley ne suivait pas automatiquement les redirections. En examinant le code source, j'ai constaté que même si Volley définissait correctement l'URL de redirection, elle ne la suivrait pas à moins que la stratégie de nouvelle tentative de la demande spécifie de "nouvelle tentative" au moins une fois. De manière inexplicable, la stratégie de nouvelle tentative par défaut définit maxNumRetries sur 0. Le correctif consiste donc à définir une stratégie de nouvelle tentative avec 1 nouvelle tentative (délai d'expiration 10 secondes et copie de sécurité 1x copiée à partir de la valeur par défaut):

request.setRetryPolicy(new DefaultRetryPolicy(10000, 1, 1.0f))

Pour référence, voici le code source:

/**
 * Constructs a new retry policy.
 * @param initialTimeoutMs The initial timeout for the policy.
 * @param maxNumRetries The maximum number of retries.
 * @param backoffMultiplier Backoff multiplier for the policy.
 */
public DefaultRetryPolicy(int initialTimeoutMs, int maxNumRetries, float backoffMultiplier) {
    mCurrentTimeoutMs = initialTimeoutMs;
    mMaxNumRetries = maxNumRetries;
    mBackoffMultiplier = backoffMultiplier;
}

Sinon, vous pouvez créer une implémentation personnalisée de RetryPolicy qui "ne tente que" de nouveau dans le cas d'un 301 ou 302.

J'espère que cela aide quelqu'un!

6
yuval

Volley prend en charge la redirection sans aucun correctif, pas besoin d'un fork distinct

Explication: Volley utilise en interne HttpClient qui, par défaut, suit 301/302 sauf indication contraire

De: http://hc.Apache.org/httpcomponents-client-4.2.x/tutorial/html/httpagent.html

ClientPNames.HANDLE_REDIRECTS = 'http.protocol.handle-redirect': définit si les redirections doivent être traitées automatiquement. Ce paramètre attend une valeur de type Java.lang.Boolean. Si ce paramètre n'est pas défini, HttpClient gérera automatiquement les redirections.

4
Eugene

En fin de compte, fusionnez les réponses de la plupart des @niko et @slott:

// Request impl class
// ...

    @Override
    public void deliverError(VolleyError error) {
        super.deliverError(error);

        Log.e(TAG, error.getMessage(), error);

        final int status = error.networkResponse.statusCode;
        // Handle 30x
        if (status == HttpURLConnection.HTTP_MOVED_PERM ||
                status == HttpURLConnection.HTTP_MOVED_TEMP ||
                status == HttpURLConnection.HTTP_SEE_OTHER) {
            final String location = error.networkResponse.headers.get("Location");
            if (BuildConfig.DEBUG) {
                Log.d(TAG, "Location: " + location);
            }
            // TODO: create new request with new location
            // TODO: enqueue new request
        }
    }

    @Override
    public String getUrl() {
        String url = super.getUrl();

        if (!url.startsWith("http://") && !url.startsWith("https://")) {
            url = "http://" + url; // use http by default
        }

        return url;
    }

Cela fonctionnait bien en surchargeant les méthodes StringRequest.

J'espère que cela peut aider n'importe qui.

1
Ruben O. Chiavone

J'utilise volley: 1.1.1 avec https url bien que la demande ait eu un problème. En creusant plus profondément, j'ai constaté que ma méthode de requête était modifiée de POST à GET en raison d'une redirection (redirection permanente 301). J'utilise nginx et dans le bloc serveur, j'avais une règle de réécriture qui était à l'origine du problème. 

En bref, tout semble bien aller avec la dernière version de volley. Ma fonction utilitaire ici-

public void makePostRequest(String url, JSONObject body, final AjaxCallback ajaxCallback) {
    try {
        JsonObjectRequest jsonObjectRequest = new JsonObjectRequest(Request.Method.POST,
                url, body, new Response.Listener<JSONObject>() {

            @Override
            public void onResponse(JSONObject response) {
                Log.d(LOG, response.toString());
                ajaxCallback.onSuccess(response);
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(LOG, error.toString());
                ajaxCallback.onError(error);
            }
        });
        singleton.getRequestQueue().add(jsonObjectRequest);
    } catch(Exception e) {
        Log.d(LOG, "Exception makePostRequest");
        e.printStackTrace();
    }
}

// separate file
public interface AjaxCallback {
    void onSuccess(JSONObject response);
    void onError(VolleyError error);
}
0
Varun Kumar