0

Following is my RetrofitApi interface

 const val USER_DETAIL = "private/{${Params.USER_NAME}}/details"

 @GET(USER_DETAIL)
 suspend fun getUsers(@Path(NetworkConstants.Params.USER_NAME) userName: String, @Query(NetworkConstants.Params.LANG) lang: String): Response<UserEntity?>

What I want is to know what is the URL after adding the query param and path to the respective url, like what is the final url before making API call.

Retrofit is making the final request url in its own library. How can i access that before making the request.

Context:

For caching purpose, I'm storing endpoints in db from the response interceptor. Now, before making another call, I want to check if that endpoint is already saved in my database or not. That's why I need to know what will be the final url.

Do I need to create my own Endpoint Builder Wrapper or does retrofit provides an easy way to access that final end point value?

Ahmad Shahwaiz
  • 1,432
  • 1
  • 17
  • 35
  • You can intercept the request in same way . if i get your question correctly . – ADM Aug 31 '21 at 11:14
  • i want to check before the request. so that i should decide should i use the cached version or should i make a network call. using intercept means call is made. and if there is no internet connection interceptor won't be called. – Ahmad Shahwaiz Aug 31 '21 at 11:15
  • 1
    For this you have build the URL before hand manually . Or you can cancel the request from interceptor(Check this one). – ADM Aug 31 '21 at 11:19
  • i tried with both addInterceptor and addNetworkInterceptor both of them are not being triggered when internet is not connected. And I need the endpoint even if I dont have internet. I guess I have to manually do this. Thanks for your comment. – Ahmad Shahwaiz Aug 31 '21 at 11:25
  • if only there was a way where retrofit provided us to build the url before making the request... @jakewharton where are you – Ahmad Shahwaiz Aug 31 '21 at 11:27
  • for future readers I added an issue here or future request: https://github.com/square/retrofit/issues/3628 – Ahmad Shahwaiz Aug 31 '21 at 11:40
  • 1
    Call yourCall = api.getUsers(params, blah); then before use use it with yourCall.enqueue you can check the url with yourCall.request().url() – Per.J Aug 31 '21 at 12:38
  • you are right, that brings to another question when to use Call and when to use retrofit2.Response... – Ahmad Shahwaiz Aug 31 '21 at 14:22

1 Answers1

0

So, I had to create wrapper class to build my end points, because retrofit doesn't expose url if you don't use retrofit CALL as return type.

I also created an issue/future request and Jake has responded: github.com/square/retrofit/issues/3628

Jake Wharton says:

If you are using Retrofit's Call you can get the backing OkHttp Request which has the URL available. If you are using any of the adapters the URL is not exposed in any way.

Following is the calling code:

 val endPoint =  EndPointBuilder()
                        .setEndPoint(NetworkConstants.Url.USER_DETAIL)
                        .addParamsAndValue(NetworkConstants.Params.USER_NAME,"")
                        .addQueryParamAndValue(NetworkConstants.Params.LANG,"en")
                        .build()

Now the EndPointBuilder class:

//accommodate query and path params of retrofit
 class EndPointBuilder {

   private val pathParamMap = hashMapOf<String, String>()
   private val queryParamMap = hashMapOf<String, String>()
   private var endPoint : String? = null

    fun setEndPoint(endPoint: String): EndPointBuilder{
        this.endPoint = endPoint
        return this
     }

    fun addParamsAndValue(param: String, value: String): EndPointBuilder{
        pathParamMap[param] = value
        return this
     }
    fun addQueryParamAndValue(param: String, value: String): EndPointBuilder{
        queryParamMap[param] = value
        return this
     }

    fun build(): String{
        for((key, value) in pathParamMap){
            endPoint = endPoint.toString().replace("{$key}",value)
        }
        var queryString = ""

        var counter  = 0
        for((key, value) in queryParamMap){
            queryString = "$queryString$key=$value"
            counter++
            if(counter < queryParamMap.size){
                queryString= "$queryString&"
            }
        }

        endPoint = endPoint.toString() +"?"+ queryString
        return endPoint.toString()
    }

Here is my retrofit interface where url (without base url) is passed as an endpoint:

@GET
suspend fun getUsers(@Url url: String): Response<UserEntity?>
Ahmad Shahwaiz
  • 1,432
  • 1
  • 17
  • 35