用于验证请求 header 值的自定义 spray.io 指令
Custom spray.io directive to validate request header value
我是 spray 新手,正在尝试编写自定义指令。如果 header 值无效,我希望该指令拒绝请求,否则请单独处理请求。
我试图吸收这个页面:
http://spray.io/documentation/1.1.2/spray-routing/key-concepts/directives/
具体来说,关于响应者链的部分。我正在尝试在插图中的 bar Directive 级别创建一些东西。我只是不知道如何将上下文不变地传递给内部路由。
下面我的 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
I'm just not getting how to pass the context unchanged to the inner
route.
Spray 为您做到!
您的代码大部分是正确的,只有 2 个简单的问题需要解决!
首先,你需要 flatMap
headerValueByName("api-key")
指令。
其次,return 类型将是 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 密钥无效时收到通知。
可以合并
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"
我是 spray 新手,正在尝试编写自定义指令。如果 header 值无效,我希望该指令拒绝请求,否则请单独处理请求。
我试图吸收这个页面: http://spray.io/documentation/1.1.2/spray-routing/key-concepts/directives/
具体来说,关于响应者链的部分。我正在尝试在插图中的 bar Directive 级别创建一些东西。我只是不知道如何将上下文不变地传递给内部路由。
下面我的 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
I'm just not getting how to pass the context unchanged to the inner route.
Spray 为您做到!
您的代码大部分是正确的,只有 2 个简单的问题需要解决!
首先,你需要 flatMap
headerValueByName("api-key")
指令。
其次,return 类型将是 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 密钥无效时收到通知。
可以合并
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"