web-dev-qa-db-de.com

Android-Volley für die Weiterleitung

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 RetryPolicyhier verwenden?

Vielen Dank.

26
Niko

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).

21
Niko

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

36
Mucahit

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.

12
slott

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!

6
yuval

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.

4
Eugene

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.JavaKLASSE 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 ..

2
uLYsseus

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.

1

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);
}
0
Varun Kumar