In retrofit, can I get the endpoint uri with all dynamic values/query params before making the call?

722 Views Asked by At

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?

1

There are 1 best solutions below

0
On BEST ANSWER

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?>