square / retrofit

A type-safe HTTP client for Android and the JVM

Home Page:https://square.github.io/retrofit/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Better support for redirects in Response class

Charchad opened this issue · comments

I'm currently working on an Android project where I needed to implement a basic OpenID Client, so for this I'm using Retrofit to perform a GET call that triggers several redirections.

So the first thing I noticed, is that from retrofit2.Response there is no way to check if the result was a redirect. I was able to solve quickly this by adding a Kotlin extension function:

fun <O> Response<O>.isRedirect() = raw().isRedirect

As you can see, you could easily add this to your Response class as the raw Response (from okhttp3) has the logic.

Then, I tried to mock the response and for my surprise there is no way to create a redirect Response. You do have proper methods to create success or error responses but there is nothing for redirects.

Maybe you can add this logic?
Thanks

In general, Retrofit wants to hide the HTTP transport layer as much as possible and expose a more semantic abstraction of the remote service which deals in friendly objects that you can work directly with. As a result, we generally want to hide concepts like redirects, TLS handshakes, DNS resolution, disk caching, etc.

We expose Response<T> because we otherwise have no means of abstracting both the success and failure case without our own type as OkHttp knows nothing about the semantic body type (the "T") you've declared. When using this type, we only expose the core concepts of an HTTP response which are the code, message, headers, and body.

Redirects are almost always an implementation detail of the HTTP transport layer. Most people don't know or care that they happened. But if you do care about redirects (or TLS handshakes or DNS resolution or disk caching) that is precisely what the raw() method is there for. It gives you access to the raw HTTP transport layer response object which has all those things.

As a result, I don't think we'll add any new APIs to Retrofit here because I don't believe the demand is high.

With regard to mocking (or faking, really), there is an overload for creating a Retrofit Response<T> which takes an OkHttp Response. This means you can craft an OkHttp Response which has a redirect Response with any additional data that you want, and then create the Retrofit Response<T> from that (API link). This will ensure that your call to raw() to check for a redirect will expose one.

Unfortunately every method that is exposed to create a Retrofit Response internally is enforcing a success or an error response, so you can't craft a redirect. Anyway, I was able to do what I wanted by wrapping the response with another class and then adding a custom CallAdapter.Factory()... far from ideal but it works.

Redirects end in a successful or error response, so the final OkHttp response will always be one of those two states. The one or more redirect responses which lead to the success or failure response are free to use any of the 3xx status codes. Retrofit never sees those responses.