Retrofit 2 — URL Handling, Resolution and Parsing

You’ve already noticed our content flash to celebrate the Retrofit 2 release. This is another post as part of our contribution to push the Retrofit community forward by sharing the knowledge about internal changes of this Retrofit release. If you worked with Retrofit 1, you know the rudimentary behavior in regard to url handling. With Retrofit 2, there’s a kind of fundamental shift in how to think and apply your urls including any type of parameter.

Retrofit Series Overview

  1. Ignore Response Payload with Call<Void> (Coming soon)
  1. Simple Error Handling
  2. Error Handling for Synchronous Requests (Coming soon)
  3. Catch Server Errors Globally with Response Interceptor (Coming soon)
  4. How to Detect Network and Conversion Errors in onFailure (Coming soon)
  1. Activate Response Caching (Etag, Last-Modified) (Coming soon)
  2. Check Response Origin (Network, Cache, or Both) (Coming soon)
  3. Force Server Cache Support with Response Interceptor (Coming soon)
  4. Support App Offline Mode by Accessing Response Caches (Coming soon)
  5. Analyze Cache Files (Coming soon)
  1. Callbacks (Coming soon)
  2. Annotations (Coming soon)
  3. Fluent Interface with Builders (Coming soon)

Url Handling Introduction

In Retrofit 2, all your urls are resolved using the HttpUrl class that’s brought to you by OkHttp 3. It’s an awesome class that does its job very well. Nonetheless, it introduces changes in the way you need to handle all your urls within your app: base and endpoint urls as well as any dynamic url defined for a specific request.

Remember: your urls in Retrofit 2 are handled like links on web pages: <a href="…">…</a>.

baseUrl Resolution

Using Retrofit, you're requesting a specific API that always has the same base address. This base address shares the same scheme and host and you can define it in a single place (using Retrofit.Builder()) and change it there if necessary without touching every endpoint in your app.

Retrofit.Builder builder = new Retrofit.Builder()  
            .baseUrl("https://your.base.url/api/");

The base url is used for every request and any endpoint value, like @GET, etc., gets resolved against this address. You should always end your base url with a trailing slash: /. And of course we tell you why: each endpoint definition with a relative path address will resolve correctly, because it appends itself to the base url that already defines or includes path parameters.

Let’s look at an example to get things straight:

# Good Practice
base url: https://futurestud.io/api/  
endpoint: my/endpoint  
Result:   https://futurestud.io/api/my/endpoint

# Bad Practice
base url: https://futurestud.io/api  
endpoint: /my/endpoint  
Result:   https://futurestud.io/my/endpoint  

The example above illustrates what happens if you don’t end your base url on a trailing slash. The api path parameter will be omitted and removed from the resulting request url.

Actually, Retrofit helps you out if you pass a base url without trailing slash. It will throw an exception and tell you that your base url needs to end on a slash.

Absolute Urls

You’ve already seen in the bad practice from above, that you can pass absolute urls to your endpoint urls. Nonetheless, this technique might be necessery in your app to call the appropriate endpoints. Over time, your backend will release a new API version. Dependending on the types of versioning, let’s assume your backend developer chose to version the API within the url. You need to bump your base url from v2 to v3. At this point, you’ll have to take care of all the breaking changes introduced by API v3. To rely on selected v2 endpoints, you can use an absolute url to directly specify an API version.

# Example 1
base url: https://futurestud.io/api/v3/  
endpoint: my/endpoint  
Result:   https://futurestud.io/api/v3/my/endpoint

# Example 2
base url: https://futurestud.io/api/v3/  
endpoint: /api/v2/another/endpoint  
Result:   https://futurestud.io/api/v2/another/endpoint  

In situations when you change your base url, you’re automatically upgrading all endpoints to use the new url and request against it. As you can see, Example 1 works like expected and just appends the endpoint url to the base url for the API call against v3. If you don’t expect a breaking change for the v3 endpoint, this is the most convenient way to jump on the upgrade train.

Example 2 illustrates the case, that you’re upgrading your base url to v3 and still use the API v2 for a selected endpoint. This might be caused due to huge upgrading efforts on your client side and you still want to profit from all the other benefits that come with API v3 for other endpoints.

Dynamic Urls or Passing a Full Url

With Retrofit 2, you’ve the ability to pass a given url to an endpoint which then is used for the request. If you want to read more about dynamic urls in Retrofit 2, there’s another post waiting for you :)

When using a dynamic url, Retrofit is very flexible and can keep your scheme from the base url. That means, if you’ve defined your base url with https and you want to make sure that all other requests in your app are also using https, you can just start your request urls with a doubled slash //. This is common practice in the web to avoid a browser warning on using secure and insecure resources on the same page.

# Example 3 — completely different url
base url: http://futurestud.io/api/  
endpoint: https://api.futurestud.io/  
Result:   https://api.futurestud.io/

# Example 4 — Keep the base url’s scheme
base url: https://futurestud.io/api/  
endpoint: //api.futurestud.io/  
Result:   https://api.futurestud.io/

# Example 5 — Keep the base url’s scheme
base url: http://futurestud.io/api/  
endpoint: //api.github.com  
Result:   http://api.github.com  

Example 3 shows you the replacement of the base url when using a completely different one. This example is useful when requesting files or images that have different locations, like some files are on your own server and others are stored on Amazon’s S3. You’re only receiving the location as an url and with Retrofit, you’re able to pass the complete url for your requesting endpoint.

As already mentioned, you can keep the base url’s scheme. In Example 4, we’re not using the path segment for the API, but instead a subdomain. We still want to keep the previously defined scheme and therefore just pass the full url with leading //.

Example 5 uses the same scheme as the defined base url, but replaces the host and path segments with the given endpoint url.

Outlook

This guide walked you through the handling of urls within Retrofit 2. If you’ve used Retrofit 1 before, the changes feel kind of strange in the first place. Nonetheless, we think the new url resolution and handling is well thought out and the HttpUrl class is a great helper to create and resolve exactly the urls you want to request.


Additional Resources


Explore the Library

Find interesting tutorials and solutions for your problems.

Miscellaneous