Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get the request context in a custom directive?

Tags:

spray

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?

like image 409
user1534422 Avatar asked Mar 19 '23 03:03

user1534422


1 Answers

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 */ } 
like image 70
4lex1v Avatar answered Apr 27 '23 18:04

4lex1v