Подтвердить что ты не робот

Android-зал для обработки перенаправления

Недавно я начал использовать Volley lib от Google для своих сетевых запросов. Один из моих запросов получает ошибку 301 для перенаправления, поэтому мой вопрос заключается в том, что может ли попытка перенаправления переназначить как-то автоматически или мне нужно обрабатывать ее вручную в parseNetworkError или использовать здесь какой-то RetryPolicy?

Спасибо.

4b9b3361

Ответ 1

Я решил, что он поймает статус http 301 или 302, считывая URL-адрес перенаправления и задавая ему запрос, а затем бросая проверку, которая запускает повтор.

Изменить: вот основные ключи в volley lib, которые я изменил:

  • Добавлен метод public void setUrl(final String url) для класса Request

  • В классе BasicNetwork добавляется проверка перенаправления после//Проверка проверки кэша, if (statusCode == HttpStatus.SC_MOVED_PERMANENTLY) || statusCode == HttpStatus.SC_MOVED_TEMPORARILY), там я читаю URL-адрес перенаправления с responseHeaders.get("location"), вызываю setUrl с объектом запроса и выбрасываю ошибку

  • Ошибка при вызове и вызывает attemptRetryOnException

  • Вам также необходимо установить RetryPolicy для Request (см. DefaultRetryPolicy для этого)

Ответ 2

Замените ваш url как url.replace( "http", "https" );

например: если ваш url выглядит так: " http://graph.facebook.......", чем это должно выглядеть так: " https://graph.facebook......."

он работает для меня

Ответ 3

Если вы не хотите изменять Volley lib, вы можете поймать 301 и вручную отправить запрос.

В вашем классе GsonRequest реализуйте deliverError и создайте новый объект Request с новым URL-адресом местоположения из заголовка и вставьте его в очередь запросов.

Что-то вроде этого:

@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);
    }
}

Таким образом, вы можете продолжать обновлять Volley и не беспокоиться о том, что происходит.

Ответ 4

Как и многие другие, меня просто смутило, почему Volley не следовало переадресации автоматически. Изучив исходный код, я обнаружил, что, хотя Volley правильно установит URL-адрес переадресации, он фактически не будет следовать за ним, если политика повторного запроса не повторит попытку хотя бы один раз. По необъяснимым причинам политика повторной попытки по умолчанию устанавливает maxNumRetries в 0. Таким образом, исправление заключается в установке политики повтора с 1 повторной попыткой (тайм-аут 10 с и 1-кратный откат по умолчанию):

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

Для справки, вот исходный код:

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

В качестве альтернативы вы можете создать собственную реализацию RetryPolicy, которая только "повторяет" в случае 301 или 302.

Надеюсь, это поможет кому-то!

Ответ 5

Volley поддерживает перенаправление без каких-либо патчей, нет необходимости в отдельной вилке

Объяснение: Volley внутренне использует HttpClient, который по умолчанию следует за 301/302, если не указано иное

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

ClientPNames.HANDLE_REDIRECTS = 'http.protocol.handle-redirects': определяет, следует ли обрабатывать переадресацию автоматически. Этот параметр ожидает значение типа java.lang.Boolean. Если этот параметр не установлен, HttpClient будет обрабатывать перенаправления автоматически.

Ответ 6

ОК, им немного поздно в игре здесь, но я недавно пытался достичь этого же аспекта, поэтому fooobar.com/questions/237920/... является лучшим, учитывая, что вы готовы разбить волейбол и сохранить его, и ответ здесь: fooobar.com/questions/237920/... - Я не уверен, как это даже сработало. Это одно место, хотя: fooobar.com/questions/237920/.... Но на самом деле он добавляет новый объект запроса в очередь NetworkDipatcher, поэтому вам также нужно как-то уведомить вызывающего, есть один грязный способ, где вы можете сделать это, не изменяя запрос объект + изменение поля "mURL", ПОЖАЛУЙСТА, ОБРАТИТЕ, ЧТО ЭТО ЗАВИСИМО ОТ ВАШЕГО ОСУЩЕСТВЛЕНИЯ ИНТЕРФЕЙСА VOLLEY RetryPolicy.java И КАК ВАШИ КЛАССЫ РАСШИРЯЮТСЯ Request.java КЛАСС, здесь вы идете: welcome REFLECTION

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

Лично я бы предпочел клонировать залп, хотя. Плюс выглядит как пример волейбола BasicNetwork класс был разработан для отказа при переадресации: https://github.com/google/volley/blob/ddfb86659df59e7293df9277da216d73c34aa800/src/test/java/com/android/volley/toolbox/BasicNetworkTest.java#L156, поэтому я думаю, что они arent слишком много склоняются к перенаправлениям, не стесняйтесь предлагать/редактировать. Всегда ищем хороший способ.

Ответ 7

В конце концов, слияние большинства @niko и @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;
    }

Он отлично работал над методами StringRequest.

Надеюсь, это может помочь кому угодно.

Ответ 8

Я использую volley: 1.1.1 с https url, хотя в запросе возникла проблема. При углублении я обнаружил, что мой метод запроса менялся с POST на GET из-за перенаправления (постоянная переадресация 301). Я использую nginx, и в серверном блоке у меня было правило перезаписи, которое вызывало проблему.

Короче говоря, все кажется хорошим с последней версией залпа. Моя функция полезности here-

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