I have this api usage now:
App.API.foo(mapOf("a" to a, "b" to b)).enqueue(responseHandler)
// my api class
@POST("/foo-v1")
fun foo(@Body map: Map<String, String>): Call<Response>
Now I have new api path: "/foo-v2"
and new baseurl that defined in runtime.
What can be my best way to do changes in runtime?
option that I think: to add @Path("version") version: String
to foo function will be like this:
@POST("/foo-{version}")
fun foo(@Body map: Map<String, String>, @Path("version") version: String): Call<Response>
its ok for one single request but in case when changed a lot of requests its not so good.
Ps another question, what can be done when for some requests need also add new path like @POST("/auth/foo-{version}")
I originally commented because I'm short on time, but I wanted to offer some quick code to illustrate the point.
Given a service like this:
interface ChangePathService {
@POST(".")
fun foo(
@Header("path") path: String,
@Body map: Map<String, String>
): Call<Response>
}
You can set your endpoint path at run time using an interceptor, which is applied to your OkHttpClient.Builder.
class ChangePathInterceptor(
private val baseUrl: String,
): Interceptor {
override fun intercept(chain: Interceptor.Chain): Response {
// This request is has "." as the path. We want to change it!
val request = chain.request()
/**
* Get the path argument via the headers. I exit early here
* with the original request going through the network but you
* can throw an exception or whatever.
*/
val path = request.header("path")
?: return chain.proceed(request)
val body = request.body // don't forget to apply your request body
/**
* Here's where you create your new request at runtime!
*/
val newRequest = Request.Builder()
.url(baseUrl+path)
.headers(request.headers)
.apply {
if(body == null) this else post(body)
}
.build()
return chain.proceed(newRequest)
}
}
EDIT: The path can be managed at runtime from the service endpoint call site. For example, a repository:
class SomeRepository(
private val service: ChangePathService,
) {
private fun getFooVersion(): String {
// do your version logic here.
}
fun callFoo(map: Map<String, String>) {
val version: String = getFooVersion() // this could be calculated once at the repository level depending on your need
val call = service.foo(
path = "/foo-$version", // interpolate version here
body = map,
)
call.enqueue(responseHandler)
}
...
}