Android volley para manejar la redirección


Recientemente comencé a usar Volley lib de Google para mis solicitudes de red. Una de mis solicitudes obtiene el error 301 para redireccionar, por lo que mi pregunta es que puede volley manejar redireccionar de alguna manera automáticamente o tengo que manejarlo manualmente en parseNetworkError o usar algún tipo de RetryPolicyaquí?

Gracias.

Author: SBerg413, 2013-07-05

8 answers

Reemplaza tu url como esa url.replace ("http", "https");

Por ejemplo: si tu url se ve así: " http://graph.facebook ......." que debería ser como: " https://graph.facebook ......."

Funciona para mí

 32
Author: Mucahit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-21 10:07:57

Lo arreglé capturando el estado http 301 o 302, leyendo la url de redirección y configurándola para solicitar y luego lanzando expection que activa reintentar.

Editar: Aquí están las teclas principales en volley lib que he modificado:

  • Método añadido public void setUrl(final String url) para la clase Request

  • En la clase BasicNetwork se añade comprobar la redirección después de / / Manejar la validación de caché, if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY) || statusCode == HttpStatus.SC_MOVED_TEMPORARILY), allí leo la url de redirección con responseHeaders.get("location"), llamo setUrl con objeto de solicitud y tiro error

  • El error get está atrapado y llama attemptRetryOnException

  • También debe tener RetryPolicy establecido para Request (ver DefaultRetryPolicy para esto)

 18
Author: Niko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-10-08 21:36:47

Si no desea modificar la liberación de volea, puede capturar el 301 y volver a enviar manualmente la solicitud.

En su clase GsonRequest implemente deliverError y cree un nuevo objeto de solicitud con la nueva url de ubicación desde el encabezado e insértelo en la cola de solicitudes.

Algo como esto:

@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 esta manera puedes seguir actualizando Volea y no tener que preocuparte de que las cosas se rompan.

 10
Author: slott,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-02-11 12:25:34

Al igual que muchos otros, simplemente estaba confundido acerca de por qué Volley no estaba siguiendo redirecciones automáticamente. Al mirar el código fuente encontré que mientras Volley configurará la URL de redirección correctamente por su cuenta, en realidad no la seguirá a menos que la política de reintento de la solicitud especifique "reintentar" al menos una vez. Inexplicablemente, la política predeterminada de reintentos establece maxNumRetries en 0. Por lo tanto, la solución es establecer una política de reintento con 1 reintento (10s de tiempo de espera y 1x de retroceso copiado desde el valor predeterminado):

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

Para referencia, aquí está el código fuente:

/**
 * 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;
}

Alternativamente, puede crear una implementación personalizada de RetryPolicy que solo "reintenta" en el caso de un 301 o 302.

Espero que esto ayude a alguien!

 6
Author: yuval,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-29 23:23:12

Volley admite la redirección sin ningún parche, sin necesidad de una bifurcación separada

Explicación: Volley utiliza internamente HttpClient que por defecto sigue 301/302 a menos que se especifique lo contrario

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

Nombres de cliente.HANDLE_REDIRECTS = ' http.protocolo.handle-redirects': define si las redirecciones deben ser manejadas automáticamente. Este parámetro espera un valor de tipo java.lang.Booleano. Si este parámetro no está establecido HttpClient manejará redirecciones automáticamente.

 4
Author: Eugene,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-17 18:25:39

Ok, estoy un poco tarde para el juego aquí, pero recientemente he estado tratando de lograr este mismo aspecto, así que https://stackoverflow.com/a/17483037/2423312 es el mejor, dado que usted está dispuesto a fork volley y mantenerlo y la respuesta aquí: https://stackoverflow.com/a/27566737/2423312 - No estoy seguro de cómo funcionó esto.Sin embargo, este es perfecto: https://stackoverflow.com/a/28454312/2423312 . Pero en realidad está agregando un nuevo objeto de solicitud a los NetworkDipatcher cola, por lo que tendrá que notificar a la persona que llama, así de alguna manera, hay una manera sucia donde puede hacer esto al no modificar el objeto de solicitud + cambiar el campo "mURL", TENGA EN CUENTA QUE ESTO DEPENDE DE SU IMPLEMENTACIÓN DE LA INTERFAZ DE VOLLEY RetryPolicy.java Y CÓMO SON SUS CLASES QUE EXTIENDEN LA CLASE Request.java, aquí tiene: REFLEXIÓN de bienvenida

Class volleyRequestClass = request.getClass().getSuperclass();
                        Field urlField = volleyRequestClass.getDeclaredField("mUrl");
                        urlField.setAccessible(true);
                        urlField.set(request, newRedirectURL);

Personalmente, preferiría clonar volea. Además, parece que la clase de ejemplo BasicNetwork de volley era diseñado para fallar en redirecciones : https://github.com/google/volley/blob/ddfb86659df59e7293df9277da216d73c34aa800/src/test/java/com/android/volley/toolbox/BasicNetworkTest.java#L156 así que supongo que no se inclinan demasiado en redirecciones, siéntete libre de sugerir / editar. Siempre buscando el buen camino..

 2
Author: uLYsseus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:09:59

Terminan haciendo una fusión de lo que la mayoría de @niko y @slott respondieron:

// 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;
    }

Funcionó bien sobreescribiendo los métodos StringRequest.

Espero que pueda ayudar a cualquiera.

 1
Author: Ruben O. Chiavone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-31 04:35:39

Estoy usando volley:1.1.1 con url https aunque la solicitud estaba teniendo algún problema. Al profundizar, descubrí que mi método de solicitud estaba cambiando de POST a GET debido a redirect (redirect permanente 301). Estoy usando nginx y en el bloque de servidor estaba teniendo una regla de reescritura que estaba causando el problema.

Así que en resumen todo parece bueno con la última versión de volley. Mi función de utilidad aquí -

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
Author: Varun Kumar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-31 15:57:13