Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic Paths in Retrofit

I'm trying to access a resource with like http://192.168.1.64:5050/api/{api_key}/updater.info.

How would I dynamically set the api_key parameter? I've tried using a RequestInterceptor without success where the base url is http://192.168.1.64:5050/api/{api_key}.

@Override
public void intercept(RequestFacade request) {
    request.addPathParam("api_key", apiKey);
}

Are there any other alternatives?

like image 754
f2prateek Avatar asked Apr 24 '14 20:04

f2prateek


People also ask

How to use dynamic url in Retrofit?

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 :) As you can see, you'll leave the @GET annotation without the endpoint url and add the @Url to the method itself.

How do I know if a url is retrofit?

one of the attributes you can assign to Retrofit builder is the client, set the client to the client from the first function. After running this code you could search for OkHttp tag in the logcat and you will see the requests and responses you made.

How do I override a base url in retrofit?

you are using it in wrong way. @URL wants the complete url to the endpoint. Is a way to override the base url you fed retrofit with. \@GET fun route(\@Url url: String = "myurl.com/api/1/route"): Observable<Route> is a valid option.


3 Answers

Use this:

@PUT("/path1/path2/{userId}")
void getSomething(
        @Path("userId") String userId
);

and you call the method like this:

String userId = "1234";
service.getSomething(userId);
like image 104
cgr Avatar answered Oct 09 '22 08:10

cgr


Path replacement does not happen inside the base URL of the API endpoint, only the relative URL string on the method. I'm going to assume you don't want to prefix the relative URLs on every one of your interface method declarations.

While poorly worded, the javadoc of Endpoint states:

Callers should always consult the instance for the latest values rather than caching the returned values.

This means that for every request the Endpoint instance will be consulted for the value of the base URL.

You can supply a custom Endpoint implementation on which you can change the API key value:

public final class FooEndpoint implements Endpoint {
  private static final String BASE = "http://192.168.1.64:5050/api/";

  private String url;

  public void setApiKey(String apiKey) {
    url = BASE + apiKey;
  }

  @Override public String getName() {
    return "default";
  }

  @Override public String getUrl() {
    if (url == null) throw new IllegalStateException("API key not set.");
    return url;
  }
}
like image 17
Jake Wharton Avatar answered Oct 09 '22 07:10

Jake Wharton


If the path parameter is not in the same position in the url for each request, for example, http://endpoint/blah/{apiKey} and http://endpoint/blah/blah/{apiKey}/blah, you could do the following.

In your APIService Interface

    @GET(/blah/{apiKey})
    void getFoo(Callback<Object> callback);

    @GET(/blah/blah/{apiKey}/blah)
    void getFooBlah(Callback<Object> callback);

Then in your ApiClient Class create a RequestInterceptor

private static APIService sAuthorizedApiService;
private static Gson gson;

static {
    gson = new GsonBuilder().setPrettyPrinting()
            .create();
}


public static synchronized APIService getApiClient(final Context context) {
    if (sAuthorizedApiService == null) {
        RequestInterceptor requestInterceptor = new RequestInterceptor() {
            @Override
            public void intercept(RequestFacade request) {
                request.addPathParam("apiKey", DataProvider.getInstance(context).getApiKey();
            }
        };

        RestAdapter restAdapter = new RestAdapter.Builder().setLogLevel(RestAdapter.LogLevel.FULL)
                .setClient(new OkClient(new OkHttpClient()))
                .setEndpoint("http://endpoint")
                .setRequestInterceptor(requestInterceptor)
                .setConverter(new GsonConverter(gson))
                .build();
        sAuthorizedApiService = restAdapter.create(GMAuthorizedApiService.class);
    }
    return sAuthorizedApiService;
}
like image 3
Jessy Conroy Avatar answered Oct 09 '22 08:10

Jessy Conroy