【问题标题】:How to get the request context in a custom directive?如何在自定义指令中获取请求上下文?
【发布时间】:2014-07-04 22:20:13
【问题描述】:

我正在 Spray 中编写一个自定义指令,它将管理任何用户请求的速率限制。

我将有一个LimitManager 来处理每个请求的自定义限制和规则。这个LimitManager需要的唯一信息是userInfocurrentRoute,即不同路由的不同限制。

所以我最终可能会为指令设置类似的内容:

def ensureLimit(): Directive0 =
  if (LimitManager.isAuthorized(userInfo, currentRoute)) {
    pass
  } else {
    reject
  }

如何在指令中获取请求上下文,以便向我的LimitManager 提供正确的信息?

【问题讨论】:

    标签: spray


    【解决方案1】:

    在 Spray 中,每个指令都是Route 上的函数,RequestContext => Unit 是函数 RequestContext => Unit 的别名。但是在强大的 Scala 暗示的帮助下,路由 DSL 有助于隐藏这一点,但您可以编写如下内容:

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

    同理:

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

    但是有一些复杂的语法技巧。

    记住!你不应该这样写:

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

    这里complete会被转换成ctx => ctx.complete("Hello"),所以你会根据你的请求返回这个函数,而不会完成真正的请求。

    因此,您可以通过一种方式来做到这一点,只需将其作为参数传递即可。您也可以使用extract 指令获取上下文,然后使用mapflatMap 制作您自己的:

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

    【讨论】:

    • 添加到记住!在扩展思想的部分,您可能会遇到需要RequestContext 引用并且还必须使用更多指令(不仅仅是complete)的情况。在这种情况下,您可以手动传入RequestContext 对象。比如如果你需要处理期货:get { ctx => onComplete(someFutureProducer(ctx)) { ... }(ctx) }
    猜你喜欢
    • 2019-02-07
    • 2012-05-04
    • 1970-01-01
    • 2014-03-20
    • 2021-10-15
    • 1970-01-01
    • 1970-01-01
    • 2016-11-04
    • 2017-08-03
    相关资源
    最近更新 更多