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
?
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 */ }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With