Retrofit 2 finally comes with an additional annotation for dynamic urls. What was a hackaround in Retrofit 1 is now just a single @Url
annotation for the endpoint declaration.
This post will show you how to make use of dynamic endpoint urls for individual requests.
Retrofit Series Overview
- Getting Started and Creating an Android Client
- Basics of API Description
- Creating a Sustainable Android Client
- URL Handling, Resolution and Parsing
- How to Change API Base Url at Runtime
- Multiple Server Environments (Develop, Staging, Production)
- Share OkHttp Client and Converters between Retrofit Instances
- Upgrade Guide from 1.9
- Beyond Android: Retrofit for Java Projects
- How to use OkHttp 3 with Retrofit 1
- Synchronous and Asynchronous Requests
- Send Objects in Request Body
- Add Custom Request Header
- Manage Request Headers in OkHttp Interceptor
- Dynamic Request Headers with @HeaderMap
- Multiple Query Parameters of Same Name
- Optional Query Parameters
- Send Data Form-Urlencoded
- Send Data Form-Urlencoded Using FieldMap
- How to Add Query Parameters to Every Request
- Add Multiple Query Parameter With QueryMap
- How to Use Dynamic Urls for Requests
- Constant, Default and Logic Values for POST and PUT Requests
- Cancel Requests
- Reuse and Analyze Requests
- Optional Path Parameters
- How to Send Plain Text Request Body
- Customize Network Timeouts
- How to Trust Unsafe SSL certificates (Self-signed, Expired)
- Dynamic Endpoint-Dependent Interceptor Actions
- How to Update Objects on the Server (PUT vs. PATCH)
- How to Delete Objects on the Server
- Introduction to (Multiple) Converters
- Adding & Customizing the Gson Converter
- Implementing Custom Converters
- How to Integrate XML Converter
- Access Mapped Objects and Raw Response Payload
- Supporting JSON and XML Responses Concurrently
- Handling of Empty Server Responses with Custom Converter
- Send JSON Requests and Receive XML Responses (or vice versa)
- Unwrapping Envelope Responses with Custom Converter
- Wrapping Requests in Envelope with Custom Converter
- Define a Custom Response Converter
Use-Case Scenarios
There might not directly come a use case to your mind that requires the definition of the endpoint url on the fly. We can give you two examples to illustrate real world scenarios.
- Profile Pictures: if your app allows users to upload their personalized profile picture, you might store them on different locations like your own server, Amazon S3 or maybe you also allow the linking of Gravatar.
- File Downloads: Files can be stored at varios locations and you want/need to be flexible to download them from any resource path.
Even though your Android app didn’t have any of the proposed functionality, you’re now in the appropriate mindset to imagine examples where dynamic urls are a good fit to make use of.
How to Use Dynamic Urls
Actually, it only requires you to add a single String parameter annotated with @Url
in your endpoint definition. Short code says more than thousand words :)
public interface UserService {
@GET
public Call<ResponseBody> profilePicture(@Url String url);
}
As you can see, you’ll leave the @GET
annotation without the endpoint url and add the @Url
to the method itself.
How Urls Resolve Against Your Base Url
That’s another interesting part and needs attention: how will the dynamic url be resolved against the defined base url? Retrofit 2 uses OkHttp’s HttpUrl
and resolves each endpoint url like a link on any website (<a href="">…</a>
).
Let’s touch some scenarios and at first look at a url that points to a profile picture stored on Amazon S3. We’ll have a base url defined and the actual call of the profilePicture
method uses a completely different one.
Retrofit retrofit = Retrofit.Builder()
.baseUrl("https://your.api.url/");
.build();
UserService service = retrofit.create(UserService.class);
service.profilePicture("https://s3.amazon.com/profile-picture/path");
// request url results in:
// https://s3.amazon.com/profile-picture/path
Because you set a completely different host including a scheme (https://s3.amazon.com
vs. https://your.api.url
), the HttpUrl
from OkHttp will resolve it to the dynamic one.
Another example: this time we point the dynamic url for our profile picture to the same server as we’ve already defined as the base url.
Retrofit retrofit = Retrofit.Builder()
.baseUrl("https://your.api.url/");
.build();
UserService service = retrofit.create(UserService.class);
service.profilePicture("profile-picture/path");
// request url results in:
// https://your.api.url/profile-picture/path
This time, the final request url gets resolved to a concatenation of the base url and our dynamically defined endpoint url. HttpUrl
will recognizes that we didn’t specify a scheme and host and therefore appends the endpoint url to the base url.
A third example: let’s assume the backend developers pushed an update to production that bumps the API’s base url to version 2.
Retrofit retrofit = Retrofit.Builder()
.baseUrl("https://your.api.url/v2/");
.build();
UserService service = retrofit.create(UserService.class);
service.profilePicture("/profile-picture/path");
// request url results in:
// https://your.api.url/profile-picture/path
The difference between the second and third examples is this: we’ve added v2/
to the base url and start the endpoint url with a leading /
. Actually, this will result in the same final request url, because endpoint urls that start with a leading slash will be appended to only the base url’s host url. Everything that comes after the host url will be omitted when using leading slashes for endpoint urls. You can fix your problem by removing the leading /
from your endpoint.
Outlook
The thing that you need to watch out for is the correct “creation” of your request urls. The examples in this article show you common pitfalls and it’s easy to fall into that trap. Make sure you’re using either full urls including scheme, host and path or you have to put in extra work to catch some issues before using the url.
We’ve recognized that the url handling in Retrofit 2 definitely requires more attention and in tomorrow’s post you’ll learn how request urls will be revolved within different scenarios.