Android-зал для обработки перенаправления
Недавно я начал использовать Volley lib от Google для своих сетевых запросов. Один из моих запросов получает ошибку 301 для перенаправления, поэтому мой вопрос заключается в том, что может ли попытка перенаправления переназначить как-то автоматически или мне нужно обрабатывать ее вручную в parseNetworkError
или использовать здесь какой-то RetryPolicy
?
Спасибо.
Ответы
Ответ 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);
}