Изменить политику перенаправления Volley Framework

Я использую платформу Volley в проекте, где мне всегда нужно обрабатывать перенаправления самостоятельно для обработки заголовков.

Как перенаправления обрабатываются, прямо сейчас зависит от метода и транспортного уровня. Я хотел бы использовать значения по умолчанию для Volley (автоматический выбор транспортного уровня) без изменения какого-либо кода залпа.

Правильное решение - всегда использовать OkHttp в качестве транспортного уровня (как упомянуто в " Проблемы и вклады в Volley"), но я хотел бы знать, есть ли способ без дополнительной структуры.

Поэтому я ищу "чистый" способ отключить автоматическую обработку перенаправления.

Редактировать:

Я предпочитаю использовать OkHttp, чтобы мне не приходилось самим определять, какую версию использовать на каком Android, но решение, предоставленное Itai Hanski, очень хорошо, когда нужно изменить поведение транспортного уровня.

4 ответа

Решение

Я думаю HttpStack реализация Volley, которая использует OkHttp в качестве своего транспорта, является лучшим решением

RequestQueue queue = Volley.newRequestQueue(this);

Network network = new BasicNetwork(new OkHttpStack());
RequestQueue queue = new RequestQueue(new DiskBasedCache(new File(getCacheDir(), "volley")), network);
queue.start();

Класс OkHttpStack:

public class OkHttpStack extends HurlStack {
private final OkHttpClient client;

public OkHttpStack() {
this(new OkHttpClient());
}

public OkHttpStack(OkHttpClient client) {
if (client == null) {
throw new NullPointerException("Client must not be null.");
}
this.client = client;
}

@Override protected HttpURLConnection createConnection(URL url) throws IOException {
return client.open(url);
}
}

Обновление: если вы используете новую версию стека okhttp, используйте

public class OkHttpStack extends HurlStack {
    private final OkUrlFactory mFactory;

    public OkHttpStack() {
        this(new OkHttpClient());
    }

    public OkHttpStack(OkHttpClient client) {
        if (client == null) {
            throw new NullPointerException("Client must not be null.");
        }
        mFactory = new OkUrlFactory(client);
    }

    @Override
    protected HttpURLConnection createConnection(URL url) throws IOException {
       return mFactory.open(url);
    }
}

Если вас не интересуют старые API (< 9), и вы просто хотите остановить залп после перенаправления, вы можете сделать

RequestQueue requestQueue = Volley.newRequestQueue(context, new HurlStack() {
    @Override
    protected HttpURLConnection createConnection(URL url) throws IOException {
        HttpURLConnection connection = super.createConnection(url);
        connection.setInstanceFollowRedirects(false);

        return connection;
    }
});

Это решение не требует другой структуры:

Volley по умолчанию использует AndroidHTTPClient или Apache (если уровень SDK ниже 8). Вы можете переопределить / наследовать изменения, которые вы хотите перенаправить в этих классах, и создать пользовательский HttpStack с ними, кормя его к Volley.newRequestQueue(),

РЕДАКТИРОВАТЬ:

Предполагая очень долго названный обычай HttpStack Реализации ваши:

HttpStack stack;
if (Build.VERSION.SDK_INT >= 9) {
    stack = new RedirectionHurlStack();
} else {
    stack = new RedirectionHttpClientStack();
}

sRequestQueue = Volley.newRequestQueue(context, stack);

Попробуйте еще раз позвонить со значением Location из заголовков сетевых ответов.

Котлин Реализация

      fun fetchRemoteList(
    url: String,
    context: Context,
    callback: OnFetchListCompleted,
    firstTry: Boolean = true
) {
    val queue = Volley.newRequestQueue(context)
    val stringRequest = StringRequest(
        Request.Method.GET, url,
        Response.Listener { response ->
            GlobalScope.launch {
                callback.fetchListSucceed()
            }
        },
        Response.ErrorListener { error ->
            val locationRedirectUrl: String? = error?.networkResponse?.headers?.get("Location")

            if (firstTry && !locationRedirectUrl.isNullOrEmpty()) {
                fetchRemoteList(locationRedirectUrl, context, callback, false)
            } else {
                callback.fetchListFailed(error?.message ?: "")
            }
        })

    queue.add(stringRequest)
}
Другие вопросы по тегам