【问题标题】:Custom spray.io directive to validate request header value自定义 spray.io 指令以验证请求标头值
【发布时间】:2016-07-20 23:52:19
【问题描述】:

我是喷雾新手,我正在尝试编写自定义指令。如果标头值无效,我希望指令拒绝请求,否则不理会请求。

我试图吸收这个页面: http://spray.io/documentation/1.1.2/spray-routing/key-concepts/directives/

特别是关于响应者链的部分。我正在尝试在插图中的 bar 指令级别创建一些东西。我只是不知道如何将上下文不变地传递给内部路由。

我下面的 else 块不正确,但表达了我正在尝试做的事情。我只是不知道如何实现它。

任何帮助将不胜感激。

trait ApiKeyDirective {
    import spray.routing.directives.HeaderDirectives._
    import spray.routing.directives.BasicDirectives._

    def validateApiKey(): Directive1 = {

       headerValueByName("api-key") {key =>
           val valid = key == "123"
           if (!valid) reject() else pass
       }
    }
}

object ApiKeyDirective extends ApiKeyDirective

【问题讨论】:

    标签: scala spray


    【解决方案1】:

    你可以组合

    headerValueByName:

    def headerValueByName(headerName: String): Directive1[String]
    

    validate:

    def validate(check: ⇒ Boolean, errorMsg: String): Directive0
    

    例如:

      def validateApiKey(route: Route) =
        headerValueByName("api-key") { key =>
          validate(key == "123", "Invalid API key") {
            route
          }
        }
    

    或者没有validate:

      def validateApiKey(route: Route) =
        headerValueByName("api-key") { key =>
          if (key == "123")
            route
          else
            reject(ValidationRejection("Invalid API key"))
        }
    

    用法:

    lazy val route = ...
        ... ~
        pathPrefix("test_directive") {
          get {
            validateApiKey {
              complete("ok")
            }
          }
        } ~
        ...
    

    从 cmd/shell 测试:

    # curl http://localhost:8080/test_directive
    Request is missing required HTTP header 'api-key'
    
    # curl http://localhost:8080/test_directive -H 'api-key: bad'
    Invalid API key
    
    # curl http://localhost:8080/test_directive -H 'api-key: 123'
    "ok"
    

    【讨论】:

    • 谢谢。查看可能的变化真的很有帮助。
    【解决方案2】:

    我只是不知道如何将上下文不变地传递给内部 路线。

    喷雾帮你搞定!

    您的代码大部分是正确的,只有 2 个简单的问题需要解决! 首先,您需要 flatMap headerValueByName("api-key") 指令。 其次,返回类型将是Directive0,因为该指令不会提供任何值。

    所以最终的代码应该是这样的:

    object ApiKeyDirective {
      import spray.routing.Directives._
    
      val validateApiKey: Directive0 =
        headerValueByName("api-key").flatMap { key =>
          val valid = key == "123"
          if (!valid) reject() else pass
        }
    
    }
    

    另外,我建议您在 reject() 块中添加自定义拒绝,以便 API 用户在他们的 api 密钥无效时得到通知。

    【讨论】:

    • 谢谢!我打算使用 AuthorizationFailedRejection 来拒绝,但为了简洁起见将其省略。
    猜你喜欢
    • 1970-01-01
    • 2018-04-23
    • 2019-09-16
    • 2023-03-21
    • 2017-05-26
    • 2014-03-07
    • 2017-05-30
    • 1970-01-01
    • 2014-08-08
    相关资源
    最近更新 更多