Change Redirect Policy of Volley Framework
Asked Answered
E

4

8

I am using the Volley framework in a project where I always need to handle the redirects myself to handle the headers.

How redirects are handled depends right now on the method and the transport layer. I would like to use the defaults of Volley (automatic selection of the transport layer) without changing any Volley code.

A valid solution is to always use OkHttp as a transport layer (as mentioned in Issues and contribution for Volley), but I would like to know if there is a way without an additional framework.

Therefore I am looking for a "clean" way to disable automatic redirect handling.

Edit:

I prefer to use OkHttp so that I don't have to manage what version to use on what Android myself, but the solution provided by Itai Hanski is very good to, when wanting to change the transport layer behavior.

Ethylethylate answered 13/9, 2013 at 12:13 Comment(0)
O
7

I think A HttpStack implementation for Volley that uses OkHttp as its transport is the best solution

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 class:

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

Update: if you are using new version of okhttp stack then use

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);
    }
}
Oversupply answered 17/9, 2013 at 6:19 Comment(5)
Does anyone know how reliable OkHttp works on older Android versions (2.2), I couldn't manage to find any tests.Ethylethylate
@Ethylethylate OkHttp supports Android 2.2 and above. For Java, the minimum requirement is 1.5 square.github.io/okhttpOversupply
OkHttpClient doesn't have open method. Your own different answer is more accurate: https://mcmap.net/q/14809/-how-to-implement-android-volley-with-okhttp-2-0Technique
Thanks for reminding ! for new okhttp stack we need change change the helper class.Oversupply
For those who dont know what is OkUrlFactory, add to gradle: compile 'com.squareup.okhttp:okhttp-urlconnection:1.6.0'Ureter
T
17

If you don't care about old APIs (< 9) and you just want volley stop following redirects you can do

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;
    }
});
Technique answered 17/9, 2014 at 9:42 Comment(2)
after this changes i also had to make a change in BasicNetwork class, in method "performRequest" and change the IF statement to: if ((statusCode < 200 || statusCode > 299) && statusCode != 303), otherwise the method fires IOException.Derzon
@Derzon can you please let me know the best way to override BasicNetwok classZsa
O
7

I think A HttpStack implementation for Volley that uses OkHttp as its transport is the best solution

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 class:

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

Update: if you are using new version of okhttp stack then use

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);
    }
}
Oversupply answered 17/9, 2013 at 6:19 Comment(5)
Does anyone know how reliable OkHttp works on older Android versions (2.2), I couldn't manage to find any tests.Ethylethylate
@Ethylethylate OkHttp supports Android 2.2 and above. For Java, the minimum requirement is 1.5 square.github.io/okhttpOversupply
OkHttpClient doesn't have open method. Your own different answer is more accurate: https://mcmap.net/q/14809/-how-to-implement-android-volley-with-okhttp-2-0Technique
Thanks for reminding ! for new okhttp stack we need change change the helper class.Oversupply
For those who dont know what is OkUrlFactory, add to gradle: compile 'com.squareup.okhttp:okhttp-urlconnection:1.6.0'Ureter
H
3

This solution doesn't require another framework:

Volley uses AndroidHTTPClient or Apache (if SDK level is 8 and under) by default. You could override / inherit the changes you want for redirection in these classes and create a custom HttpStack with them, feeding it to the Volley.newRequestQueue().

EDIT:

Assuming the very long named custom HttpStack implementations are yours:

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

sRequestQueue = Volley.newRequestQueue(context, stack);
Hornback answered 16/9, 2013 at 9:21 Comment(3)
In this solution I disable the automatic choosing of the best transportation layer and have to implement a switch myself, right?Ethylethylate
Just to clarify: this is a good solution, but I preferred the one with OkHttp over this. I will also write this in my Question. Thanks for your help!Ethylethylate
Hope that works out! I kind of thought you were looking for a solution not involving another 3rd party libraryHornback
M
1

Try on more call with the Location value from the network response headers

Kotlin Implementation

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)
}
Marbles answered 11/12, 2020 at 2:12 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.