How to get the request context in a custom directive?

spray

Solution

In Spray every directive is a function over a `Route`, which is an alias for a function `RequestContext => Unit`. But with the help of mighty Scala implicates, Routing DSL helps to hide this, but you can write stuff like this:

val route: Route = get { (ctx: RequestContext) => // this can be omitted, just for info
  ctx.complete("Hello")
}

it is the same as:

val route: Route = get { complete("Hello") }

But with some complicated syntax tricks.

REMEMBER! That you should never write like this:

val route = get { ctx =>
  complete("Alloha")
}

In here `complete` would be transformed into `ctx => ctx.complete("Hello")`, so you would return this function on your request and won't complete the real request.

So one way how you can do it, simply pass as an argument. Also you can use `extract` directive, to get the context and then use `map` or `flatMap` to make your own:

val myDirective = extract(identity) map { ctx => /* Your directive */ } 

Problem

I'm writing a custom directive in Spray that is going to manage the rate limiting for any user request. I'll have a `LimitManager` somewhere that will handle custom limits and rules for every request. The only information needed by this `LimitManager` is `userInfo` and `currentRoute`, i.e. different limits for different routes. So I will probably end up having something like this for the directive: ``` def ensureLimit(): Directive0 = if (LimitManager.isAuthorized(userInfo, currentRoute)) { pass } else { reject } ``` How can I get the request context inside a directive so I can provide the correct information to my `LimitManager`?

Original source