Interception per route

If you just want to intercept some calls for a specific route, you have to create a Route node (usually by calling createChild) and intercept that node.

For example, for creating a timeout for a route, you could do the following:

  1. fun Route.routeTimeout(time: Long, unit: TimeUnit = TimeUnit.SECONDS, callback: Route.() -> Unit): Route {
  2. // With createChild, we create a child node for this received Route
  3. val routeWithTimeout = this.createChild(object : RouteSelector(1.0) {
  4. override fun evaluate(context: RoutingResolveContext, segmentIndex: Int): RouteSelectorEvaluation =
  5. RouteSelectorEvaluation.Constant
  6. })
  7. // Intercepts calls from this route at the features step
  8. routeWithTimeout.intercept(ApplicationCallPipeline.Features) {
  9. withTimeout(time, unit) {
  10. proceed() // With proceed we can define code to be executed before and after the call
  11. }
  12. }
  13. // Configure this route with the block provided by the user
  14. callback(routeWithTimeout)
  15. return routeWithTimeout
  16. }

Intercepting any Route node

The Route class defines an intercept method that applies to that route node or any other inner route:

  1. /// Installs an interceptor into this route which will be called when this or a child route is selected for a call
  2. fun Route.intercept(phase: PipelinePhase, block: PipelineInterceptor<Unit, ApplicationCall>)

Getting the route being handled

You can get the route being handled by casting the call: ApplicationCall to RoutingApplicationCall that has a route: Route property.

Getting the route path

Route overrides the toString() method to generate a path to the route, something like:

  1. override fun Route.toString() = when {
  2. parent == null -> "/"
  3. parent.parent == null -> "/$selector"
  4. else -> "$parent/$selector"
  5. }

How to intercept preventing additional executions

  1. intercept(ApplicationCallPipeline.Setup) {
  2. if (call.request.path() == "/admin/book") {
  3. call.respondText {
  4. "intercept book"
  5. }
  6. // Truncate the route response. If there is no finish() function,
  7. // the route /book will still respond to the processing, and the pipeline will be unwritable.
  8. return@intercept finish()
  9. }
  10. }

Hooking before and after routing

You can globally intercept the routing calls by using the events Routing.RoutingCallStarted and Routing.RoutingCallFinished:

  1. pipeline.environment.monitor.subscribe(Routing.RoutingCallStarted) { call: RoutingApplicationCall ->
  2. println("Route started: ${call.route}")
  3. }
  4. pipeline.environment.monitor.subscribe(Routing.RoutingCallFinished) { call: RoutingApplicationCall ->
  5. println("Route completed: ${call.route}")
  6. }

You can see a full example of this in the Metrics feature.