Clarence
08/05/2024, 8:25 AMfun Application.main() {
routing {
get("/house/{id}") {
val id = call.parameters["id"] // this works
call.respondText("House ID: $id")
}
}
val plugin = createApplicationPlugin("plugin") {
onCall { call ->
val id = call.parameters["id"] // this doesn't work
<http://call.application.log.info|call.application.log.info>("House ID: $id")
}
}
install(plugin)
}Aleksei Tirman [JB]
08/05/2024, 8:37 AMval plugin = createRouteScopedPlugin("plugin") {
onCall { call ->
val id = call.parameters["id"] // this doesn't work
<http://call.application.log.info|call.application.log.info>("House ID: $id")
}
}
embeddedServer(Netty, port = 3333) {
routing {
install(plugin)
get("/house/{id}") {
val id = call.parameters["id"] // this works
call.respondText("House ID: $id")
}
}
}.start(wait = true)Clarence
08/05/2024, 8:50 AMAleksei Tirman [JB]
08/05/2024, 8:51 AMClarence
08/05/2024, 9:04 AMCallSetup should trigger before onCall but this isn't the case when I add this hook on the route scoped plugin:
fun <http://Application.app|Application.app>() {
val key = AttributeKey<String>("route")
val routePlugin = createRouteScopedPlugin("route") {
on(CallSetup) { call ->
<http://call.application.log.info|call.application.log.info>("route") // triggers 2nd
call.attributes.put(key, "route")
}
}
val applicationPlugin = createApplicationPlugin("app") {
onCall { call ->
val value = call.attributes.getOrNull(key)
<http://call.application.log.info|call.application.log.info>("app $value") // triggers 1st
}
}
install(applicationPlugin)
routing {
install(routePlugin)
get("/house/{id}") {
val id = call.parameters["id"] // this works
call.respondText("House ID: $id")
}
}
}Aleksei Tirman [JB]
08/05/2024, 9:53 AMApplicationCallPipeline which has the Plugins and the Call phases, which are executed in the respective order. The onCall hook is executed during the Plugins phase. In the Call phase, the whole routing is executed, so the CallSetup hook is triggered after the onCall .Clarence
08/05/2024, 11:06 AMCallSetup is mapped to the Setup phase which should occur before the Plugins phase, but because we install the plugin to the route, is that why it will always happen during the Call phase?
In this case, is it ever possible to have a route scoped plugin that would trigger before the application plugin? I wanted to create a plugin that would do the following:
1. Get information from the request parameters and store it in the call.attributes
2. Access the call.attributes in the call logging plugin config and add them to the MDCClarence
08/05/2024, 11:12 AMCallLogging plugin, we can add fields to the MDC context of the call, is this possible without the usage of the plugin?Aleksei Tirman [JB]
08/05/2024, 12:24 PMI saw thatYes, because the entire routing is executed during theis mapped to theCallSetupphase which should occur before theSetupphase, but because we install the plugin to the route, is that why it will always happen during thePluginsphase?Call
Call phase and the Setup phase is of the routing's call pipeline (routing is a call pipeline).
In this case, is it ever possible to have a route scoped plugin that would trigger before the application plugin?Only if the application plugin intercepts the phases that go after the
Call phaseAleksei Tirman [JB]
08/05/2024, 12:26 PMClarence
08/05/2024, 10:29 PMcall.parameters eg: /house/3
2. Call an external service to fetch some data using the parameters eg: service.getNameOfHouseOwner(id)
3. Store the data in the call.attributes state eg. call.attributes.put(name, houseOwnerName)
4. In the call logging plugin (application plugin) I want to access the state that I have stored and put it in the MDC
install(CallLogging) { mdc("data") { call.attributes[name] }}Aleksei Tirman [JB]
08/06/2024, 7:58 AMid parameter:
embeddedServer(Netty, port = 3333) {
install(CallLogging) {
mdc("test") { call ->
call.attributes[key]
}
}
routing {
get("/test/{id}") {
val id = call.parameters["id"]
if (id != null) {
call.attributes.put(key, id)
}
call.respondText { "OK" }
}
}
}.start(wait = true)Clarence
08/06/2024, 8:18 AMCall phase while the plugin doesn't...
And while this works, it isn't optimal. I wanted to use a plugin to do this functionality for a group of routes that all have the same parameters and populate fields based on it. Without the plugin I would need to repeat the same boilerplate code for each route.
I have made some compromises since it doesn't work currently, I created a new request logging plugin with the onCallRespomd hook and log our requests combined with our call.attributes that we save in our route scoped plugin