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. Getting Started and Creating an Android Client
  2. Retrofit 2 — Basics of API Description
  3. Retrofit 2 — Creating a Sustainable Android Client
  4. Synchronous and Asynchronous Requests
  5. Send Objects in Request Body
  6. Add Custom Request Header
  7. Retrofit 2 — Manage Request Headers in OkHttp Interceptor
  8. Retrofit 2 — Dynamic Request Headers with @HeaderMap
  9. Multiple Query Parameters of Same Name
  10. Optional Query Parameters
  11. Using the Log Level to Debug Requests
  12. Retrofit 2 — Log Requests and Responses
  13. Retrofit 2 — Enable Logging for Development Builds Only
  14. How to Upload Files to Server
  15. Retrofit 2 — How to Upload Files to Server
  16. Retrofit 2 — How to Upload Multiple Files to Server
  17. Retrofit 2 — Passing Multiple Parts Along a File with @PartMap
  18. Basic Authentication on Android
  19. Token Authentication on Android
  20. OAuth on Android
  21. Retrofit 2 — Hawk Authentication on Android
  22. How to Refresh an Access Token
  23. Retrofit 2 — Upgrade Guide from 1.9
  24. Retrofit 2 — Simple Error Handling
  25. How to use OkHttp 3 with Retrofit 1
  26. Send Data Form-Urlencoded
  27. Send Data Form-Urlencoded Using FieldMap
  28. Retrofit 2 — How to Add Query Parameters to Every Request
  29. Retrofit 2 — Add Multiple Query Parameter With QueryMap
  30. Retrofit 2 — How to Use Dynamic Urls for Requests
  31. Retrofit 2 — URL Handling, Resolution and Parsing
  32. Retrofit 2 — Constant, Default and Logic Values for POST and PUT Requests
  33. Retrofit 2 — How to Download Files from Server
  34. Retrofit 2 — Cancel Requests
  35. Retrofit 2 — Reuse and Analyze Requests
  36. Retrofit 2 — How to Change API Base Url at Runtime
  37. Optional Path Parameters
  38. Retrofit 2 — How to Send Plain Text Request Body
  39. Retrofit 2 — Pagination Using Query Parameter
  40. Retrofit 2 — Pagination Using Link Header and Dynamic Urls (Like GitHub)
  41. Retrofit 2 — Pagination Using Range Header Fields (Like Heroku)
  42. How to Integrate XML Converter
  43. Define a Custom Response Converter
  44. Retrofit 2 — Introduction to (Multiple) Converters
  45. Retrofit 2 — Adding & Customizing the Gson Converter
  46. Retrofit 2 — Implementing Custom Converters
  47. Retrofit 2 — Basics of Mocking Server Responses
  48. Retrofit 2 — Customizing Network Behavior of Mocked Server Responses (soon)
  49. Java Basics for Retrofit — Callbacks (soon)
  50. Java Basics for Retrofit — Annotations (soon)
  51. Java Basics for Retrofit — Fluent Interface with Builders (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 Practise
base url: https://futurestud.io/api/  
endpoint: my/endpoint  
Result:   https://futurestud.io/api/my/endpoint

# Bad Practise
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 practise 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 practise 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