ktor
ktor copied to clipboard
Add optionalRoute
Subsystem Server.
Motivation Optional route allows a path segment to optionally exist.
One example where this is useful is in API versioning and rerouting “missing version” to the latest version without a redirect:
fun Application.installRoutes() = routing {
optionalRoute("v1") {
// ...
}
}
In this case, both api.domain.com/v1/some-route
and api.domain.com/some-route
would point to the same place.
Solution This is a draft PR, lifted from Doist/ffs. I'm happy to add a ticket in YT, review the structure for a tighter integration, add tests, and so forth, but would prefer determining if there's interest in this first.
Hi @goncalossilva We already have functionaluty for optional path parameters. But as I understand, you need optional constant path segments, right? For path parameters you can use this code
@Test
fun testOptionalPathParameter() = testApplication {
routing {
route("{test?}") {
handle { call.respond(call.parameters["test"] ?: "missing") }
}
}
assertEquals("asd", client.get("/asd").bodyAsText())
assertEquals("missing", client.get("/").bodyAsText())
}
Exactly. The issue with optional path parameters is that they can only be used at the end of a path, while an optional route can be set anywhere in the path.
Thinking back to the API example I alluded to in the original post, both of these could work and point to the same route:
api.domain.com/v1/organizations/1/edit
api.domain.com/organizations/1/edit
A test could be:
@Test
fun testOptionalRouteParameter() = testApplication {
routing {
optionalRoute("optional") {
route("test") {
handle { call.respond("here") }
}
}
}
assertEquals("here", client.get("/optional/test").bodyAsText())
assertEquals("here", client.get("/test").bodyAsText())
}
Hey @goncalossilva, thanks for the PR. Could you add some tests and run ./gradlew apiDump
and commit changes?