Home > Back-end >  OkHttp client generates diffrent URL for retrofit
OkHttp client generates diffrent URL for retrofit

Time:09-09

I am developing a simple app to fetch now playing movie details from https://www.themoviedb.org/ API. This is the URL to which I need to perform the API call.

https://api.themoviedb.org/3/movie/now_playing?api_key=<<api_key>>

I am using retrofit to make the API call like this.

@GET("/movie/now_playing")
fun getNowPlayingMovies(): Single<List<MovieData>>

and I am using Base Url and API key as variables in the client class.

private val BASE_URL = "https://api.themoviedb.org/3/"
private val API_KEY = "xxxxxxxxxxxxxxxxxxxxxxxxxxx"

Since the best way to add the api key as a query parameter to the URL is by using a request Interceptor , I created an intercepted to intercept the request and add the api key as a query parameter.

private fun getInterceptor() : Interceptor{
    if (requestInterceptor == null){
       requestInterceptor = Interceptor{

           val url = it.request()
               .url
               .newBuilder()
               .addQueryParameter("api_key" , API_KEY)
               .build()

           val request = it.request()
               .newBuilder()
               .url(url)
               .build()

           return@Interceptor it.proceed(request)
       }
    }
    return requestInterceptor
}

Then added this interceptor along with logging interceptor to the OkHttp Client.

    private fun getOkHttpClient() : OkHttpClient{

        var httLog : HttpLoggingInterceptor = HttpLoggingInterceptor()
        httLog.setLevel(HttpLoggingInterceptor.Level.BODY)

        val okHttpClient = OkHttpClient.Builder()
           .addInterceptor(getInterceptor()).addInterceptor(httLog)
           .connectTimeout(60 , TimeUnit.SECONDS)
           .build()

    return okHttpClient
}

And then build the retrofit client. In which I add the base URL.

        var retrofit : Retrofit = Retrofit.Builder()
        .baseUrl(BASE_URL)
        .client(getOkHttpClient())
        .addConverterFactory(getGsonConverterFactory())
        .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
        .build()

The problem is , the entire URL made using the BASE_URL and the api as a Query Paramter , Should be like this

https://api.themoviedb.org/3/movie/now_playing?api_key=**********

But in the logging interceptor I am getting this as the url

https://api.themoviedb.org/movie/now_playing?api_key=**********

which has a different BASE_URL than the one I provided in retrofit. It is giving me a 404 error.

I cannot seem to figure out why this is causing. I logged on different places and I believe the request Interceptor is intercepting a different URL than the BASE_URL.

This is my entire codebase, it would be very helpful if there are any other improvements in the code , I am new to android development and Kotlin. Thank You.

interface MoviesApiServiceRx {

    @GET("/movie/now_playing")
    fun getNowPlayingMovies(): Single<List<MovieData>>
}

class MoviesRetrofitClient() {

private val BASE_URL = "https://api.themoviedb.org/3/"
private val API_KEY = "9a976526fce8c29aaa35eb4a1e654d3c"

private var moviesApiServiceRx : MoviesApiServiceRx
private var gsonConverterFactory : GsonConverterFactory
private var requestInterceptor : Interceptor

init {
    moviesApiServiceRx = getMoviesApiServiceRx()
    gsonConverterFactory = getGsonConverterFactory()
    requestInterceptor = getInterceptor()
}

private fun getInterceptor() : Interceptor{
    if (requestInterceptor == null){
       requestInterceptor = Interceptor{

           val url = it.request()
               .url
               .newBuilder()
               .addQueryParameter("api_key" , API_KEY)
               .build()

           val request = it.request()
               .newBuilder()
               .url(url)
               .build()

           return@Interceptor it.proceed(request)
       }
    }
    return requestInterceptor
}

private fun getGsonConverterFactory() : GsonConverterFactory{
    if (gsonConverterFactory == null){
        gsonConverterFactory = GsonConverterFactory.create();
    }
    return gsonConverterFactory
}

private fun getOkHttpClient() : OkHttpClient{

    var httLog : HttpLoggingInterceptor = HttpLoggingInterceptor()
    httLog.setLevel(HttpLoggingInterceptor.Level.BODY)

    val okHttpClient = OkHttpClient.Builder()
       .addInterceptor(getInterceptor()).addInterceptor(httLog)
       .connectTimeout(60 , TimeUnit.SECONDS)
       .build()

    return okHttpClient
}

private fun getMoviesApiServiceRx() : MoviesApiServiceRx{

    if (moviesApiServiceRx == null){


        var retrofit : Retrofit = Retrofit.Builder()
            .baseUrl(BASE_URL)
            .client(getOkHttpClient())
            .addConverterFactory(getGsonConverterFactory())
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .build()

        moviesApiServiceRx = retrofit.create(MoviesApiServiceRx::class.java)
    }

    return moviesApiServiceRx
}

fun getNowPlayingMovies(): Single<List<MovieData>> {
    return getMoviesApiServiceRx().
    getNowPlayingMovies()
}

}

CodePudding user response:

two options

interface MoviesApiServiceRx {

  @GET("/3/movie/now_playing")
  fun getNowPlayingMovies(): Single<List<MovieData>>
}

private val BASE_URL = "https://api.themoviedb.org/"

or

interface MoviesApiServiceRx {

  @GET("movie/now_playing")
  fun getNowPlayingMovies(): Single<List<MovieData>>
}

private val BASE_URL = "https://api.themoviedb.org/3/"

CodePudding user response:

Change

@GET("/movie/now_playing")

to

@GET("movie/now_playing")

The / at the beginning refers to the root so it will replace whatever there is after the service name.

  • Related