Ich habe vor kurzem begonnen, Volley lib von Google für meine Netzwerkanfragen zu verwenden. Eine meiner Anfragen erhält den Fehler 301 für die Weiterleitung. Meine Frage ist also, dass Volleys irgendwie automatisch umgeleitet werden können oder muss ich sie manuell in parseNetworkError
behandeln oder eine Art RetryPolicy
hier verwenden?
Vielen Dank.
Ich habe es behoben, der den http-Status 301 oder 302 einfängt, die Umleitungs-URL einliest und auf "Request" und dann "Expection" setzt, was einen Neuversuch auslöst.
Edit: Hier sind die wichtigsten Schlüssel in der Volley-Lib, die ich modifiziert habe:
Die Methode public void setUrl(final String url)
für die Klasse Request
wurde hinzugefügt.
In der Klasse BasicNetwork wird nach // Überprüfung der Cache-Validierung if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY) || statusCode == HttpStatus.SC_MOVED_TEMPORARILY)
die Umleitung geprüft. Dort habe ich die Weiterleitungs-URL mit responseHeaders.get("location")
gelesen, setUrl
mit Request-Objekt aufgerufen und einen Fehler gemeldet
Fehler get get und es ruft attemptRetryOnException
auf
Sie müssen auch RetryPolicy
für die Request
setzen (siehe hierzu DefaultRetryPolicy
).
Ersetzen Sie Ihre URL wie diese url.replace ("http", "https");
zum Beispiel: wenn Ihre URL so aussieht: " http: //graph.facebook ......." alsit sollte wie folgt aussehen: " https: // graph .Facebook ......."
für mich geht das
Wenn Sie die Volley-Bibliothek nicht ändern möchten, können Sie die 301 abfangen und die Anforderung manuell erneut senden.
Implementieren Sie in Ihrer GsonRequest-Klasse deliverError und erstellen Sie ein neues Request-Objekt mit der neuen Location-URL aus dem Header und fügen Sie dieses in die Anforderungswarteschlange ein.
Etwas wie das:
@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);
}
}
Auf diese Weise können Sie Volley ständig aktualisieren und müssen sich keine Sorgen darüber machen, dass Dinge kaputt gehen.
Wie viele andere war ich einfach verwirrt, warum Volley Umleitungen nicht automatisch folgte. Beim Durchsehen des Quellcodes habe ich festgestellt, dass Volley zwar die Weiterleitungs-URL selbstständig setzt, jedoch nicht wirklich folgt, es sei denn, die Wiederholungsrichtlinie der Anforderung legt fest, dass mindestens einmal "erneut versucht" wird. Aus unerklärlichen Gründen setzt maxNumRetries
für die Standardwiederholungsrichtlinie "0". Daher besteht die Lösung darin, eine Wiederholungsrichtlinie mit 1 Wiederholungsversuch (10 Sekunden Timeout und 1x aus dem Standard kopiert) festzulegen:
request.setRetryPolicy(new DefaultRetryPolicy(10000, 1, 1.0f))
Zur Referenz hier der Quellcode:
/**
* 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;
}
Alternativ können Sie eine benutzerdefinierte Implementierung von RetryPolicy
erstellen, die nur im Fall eines 301 oder 302 "wiederholt" wird.
Hoffe das hilft jemandem!
Volley unterstützt die Umleitung ohne Patches, eine separate Gabel ist nicht erforderlich
Erläuterung: Volley verwendet intern HttpClient
, die standardmäßig auf 301/302 folgt, sofern nicht anders angegeben
Von: http://hc.Apache.org/httpcomponents-client-4.2.x/tutorial/html/httpagent.html
ClientPNames.HANDLE_REDIRECTS = 'http.protocol.handle-redirects': Definiert, ob Weiterleitungen automatisch verarbeitet werden sollen. Dieser Parameter erwartet einen Wert vom Typ Java.lang.Boolean. Wenn dieser Parameter nicht festgelegt ist, behandelt HttpClient Umleitungen automatisch.
oK, ich bin ein bisschen spät dran im Spiel, aber ich habe vor kurzem versucht, denselben Aspekt zu erreichen, daher ist https://stackoverflow.com/a/17483037/2423312 der beste, wenn man bedenkt Ich bin bereit, die Salve zu verteidigen und aufrechtzuerhalten, und die Antwort hier: https://stackoverflow.com/a/27566737/2423312 - Ich bin mir nicht sicher, wie das überhaupt funktioniert hat. Dieses ist jedoch genau richtig: https://stackoverflow.com/a/28454312/2423312 . Aber es fügt tatsächlich ein neues Anforderungsobjekt zur Warteschlange von NetworkDipatcher
hinzu, so dass Sie den Anrufer auch irgendwie benachrichtigen müssen. Es gibt eine verschmutzte Methode, wo Sie dies tun können, indem Sie die Option nicht ändern Objekt anfragen + Feld "mURL" ändern, BITTE BEACHTEN SIE, DASS DIESES IS ABHÄNGIG VON IHRER UMSETZUNG VON VOLleys RetryPolicy.Java
SCHNITTSTELLE UND WIE IHRE KLASSEN ERWEITERT Request.Java
KLASSE SIND, hier geht es: welcome REFLECTION
Class volleyRequestClass = request.getClass().getSuperclass();
Field urlField = volleyRequestClass.getDeclaredField("mUrl");
urlField.setAccessible(true);
urlField.set(request, newRedirectURL);
Persönlich würde ich es vorziehen, Volley zu klonen. Plus sieht aus wie das Beispiel von Volley BasicNetwork
, das bei Umleitungen fehlgeschlagen ist: https://github.com/google/volley/blob/ddfb86659df59e7293df9277da216d73c34aa800/src/test/Java/com/Android/volley/tool/Booler/collector/box5 L156 Ich denke, sie sind nicht zu sehr auf Weiterleitungen angewiesen. Immer auf der Suche nach einem guten Weg ..
Am Ende eine Zusammenfassung der Antworten von @niko und @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;
}
Es hat gut funktioniert und überschreibt StringRequest
Methoden.
Ich hoffe es kann jedem helfen.
Ich benutze volley: 1.1.1 mit https url, obwohl die Anfrage einige Probleme hatte. Beim tieferen Graben stellte ich fest, dass meine Anforderungsmethode aufgrund von Weiterleitung (permanente Weiterleitung 301) von POST in GET geändert wurde. Ich verwende nginx und im Serverblock hatte ich eine Regel zum Umschreiben, die das Problem verursachte.
Kurz gesagt, mit der neuesten Version von Volley scheint alles gut zu sein. Meine Nutzenfunktion hier-
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);
}