user2880827
user2880827

Reputation: 113

Ktor custom feature swap url

Im trying to add a custom feature in Ktor. It's basically a url swapper (we have a scenario where domains might be changed during anytime & can't update the client everytime).

We get the swapper list available and need a CustomFeature in Ktor to swap the url based on list. However, the context.request or request.url - everything is val and Im not able to assign new url to the request.

In Retrofit, it used to work like this


            if (currentUrl.contains(urlSwapper.oldUrl)) {

                val newUrl = currentUrl.replace(urlSwapper.oldUrl, urlSwapper.newUrl)
                val newHttpUrl = request.url.newBuilder(newUrl)!!.build()

                // build a new request with the new url. replace it

                request = request.newBuilder().url(newHttpUrl).build()
                break
            }
        }

In Ktor feature, Im trying something like this

            scope.requestPipeline.intercept(HttpRequestPipeline.Transform) {
                val currentUrl =
                    context.url.protocol.name + "://" + context.url.host + context.url.encodedPath

                for (urlSwapper in feature.urlSwappers) {
                    if (currentUrl.contains(urlSwapper.oldUrl)) {
                        val newUrl = currentUrl.replace(urlSwapper.oldUrl, urlSwapper.newUrl)
                        val newHttpUrl = Url(newUrl)
                        context.url(url = newHttpUrl)
                        break
                    }
                }
                proceedWith(subject)
            }
        }

Is this the right way to do this ?

Upvotes: 1

Views: 623

Answers (1)

Aleksei Tirman
Aleksei Tirman

Reputation: 7139

Generally yes, this is the right way. I have a few recommendations:

  1. Intercept the sendPipeline instead of the requestPipeline.

An example:

client.sendPipeline.intercept(HttpSendPipeline.State) {
    context.url(url = newUrl)
}
  1. Get rid of proceedWith(subject) call because it's redundant.
  2. Try to use Url objects instead of strings. You can get the current URL without affecting context by cloning UrlBuilder and building Url from it: context.url.clone().build()

Upvotes: 1

Related Questions