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 RetryPolicy
ici?
Merci.
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).
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
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.
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!
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.
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.
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);
}