21

I have some service urls with the same baseUrl. For some urls there will be some common used parameters, for example an apiVersion or locale. But they don't have to be in every url, so I can't add them to the baseUrl.

.../api/{apiVersion}/{locale}/event/{eventId}
.../api/{apiVersion}/{locale}/venues
.../api/{apiVersion}/configuration

I don't want to add these parameters in the retrofit interface. In retrofit 1, I made an interceptor and used RequestFacade.addPathParam(..., ...) to fill these common path parameters for every url.

For retrofit 2, I can't seem to find a proper way to do this with okhttp. The only way I see this being possible right now is to get the HttpUrl from Chain.request().httpUrl(); in an okhttp Interceptor and manipulate that one myself, but I don't know if this is the best way to go.

Has anyone come across a better way to replace path parameters in an okhttp Interceptor?

At the time of writing I'm using retrofit:2.0.0-beta2 and okhttp:2.7.2.

Siebe
  • 942
  • 2
  • 10
  • 27
  • 1
    Have a look at this answer http://stackoverflow.com/a/31002094 . – mtotschnig Mar 18 '16 at 12:13
  • @mtotschnig there is no up to date answer(using OkHttp 3+ & Retrofit 2+) on that thread. – Singed Apr 13 '16 at 15:11
  • @Singed the answer I link to works for me with Retrofit2 and OkHttp 3 – mtotschnig Apr 13 '16 at 20:30
  • 2
    @mtotschnig oh sure, that works, but doesn't solve the problem. The problem is we have a retrofit interface with a lot of methods. We don't want to set path to each of them manually, we want to do it in one place. – Singed Apr 14 '16 at 07:04

2 Answers2

14

For retrofit 2, I can't seem to find a proper way to do this with okhttp. The only way I see this being possible right now is to get the HttpUrl from Chain.request().httpUrl(); in an okhttp Interceptor and manipulate that one myself, but I don't know if this is the best way to go.

My implementation using okhttp:3.2

    class PathParamInterceptor implements Interceptor {
        private final String mKey;
        private final String mValue;

        private PathParamInterceptor(String key, String value) {
            mKey = String.format("{%s}", key);
            mValue = value;
        }

        @Override
        public Response intercept(Chain chain) throws IOException {
            Request originalRequest = chain.request();

            HttpUrl.Builder urlBuilder = originalRequest.url().newBuilder();
            List<String> segments = originalRequest.url().pathSegments();

            for (int i = 0; i < segments.size(); i++) {
                if (mKey.equalsIgnoreCase(segments.get(i))) {
                    urlBuilder.setPathSegment(i, mValue);
                }
            }

            Request request = originalRequest.newBuilder()
                    .url(urlBuilder.build())
                    .build();
            return chain.proceed(request);
        }
    }
Andriy Petruk
  • 216
  • 4
  • 4
  • This helped me. Getting the path segments and looping through them is safer, since the code won't break if the path segment ever changes. – OldSchool4664 Jan 10 '17 at 18:24
  • I make it same but i have a problem. Retrofit call first witheout replace and then with the replaced.. Can you tell me why? https://stackoverflow.com/questions/51209066/retrofit2-put-token-in-url-with-placeholder – Andreas Jul 09 '18 at 06:17
-1

Hi you can use this way:

@GET("/api/{apiVersion}/{locale}/venues")
Call<FilterResponse> getLocaleVenues
          @Path("apiVersion") int apiVersion,
          @Path("locale") String locale
);

Hope it helps.

azwar_akbar
  • 1,451
  • 18
  • 27