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 theCallSetup
phase which should occur before theSetup
phase, but because we install the plugin to the route, is that why it will always happen during thePlugins
phase?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