喷涂:在范围内引入RequestContext会导致超时

Jen*_*olm 5 scala http-headers spray

嗨斯卡拉和喷人!

我有一个小烦人的问题,从RequestContext它上面提取HTTP'Accept'标题并进行匹配.在这样的正常路线上:

get {
  respondWithMediaType(`text/plain`) {
    complete ( "Hello World!" )
  }
}
Run Code Online (Sandbox Code Playgroud)

它就像一个魅力.但每当我将上下文纳入范围时(如指令文档中所建议):

get { context => {
  respondWithMediaType(`text/plain`) {
    complete ( "Hello World!" )
  }
} }
Run Code Online (Sandbox Code Playgroud)

结果将成为以下错误消息:

The server was not able to produce a timely response to your request.
Run Code Online (Sandbox Code Playgroud)

我对Spray很新,但对我来说看起来很奇怪,将一个(否则是隐式的)对象带入范围会产生如此奇怪的副作用.你们中有谁知道发生了什么事吗?

jru*_*lph 8

RequestContext很少需要直接访问.实际上,如果要编写自定义指令,则只需要它.通常可以使用预定义指令之一来处理常见任务和提取通常的数据位.

看来你想做的是手动内容类型协商.实际上,您不必手动执行此操作,因为喷涂会针对常见数据结构自动执行内容类型.你的例子可以缩短为

get {
  complete("Hello World!")
}
Run Code Online (Sandbox Code Playgroud)

complete使用字符串调用时,响应将始终为类型text/plain.如果客户端发送带有Accept不接受请求的标头text/plain的请求,则服务器已经拒绝该请求.

如果要自定义可从Scala数据类型提供的各种内容类型,则需要提供自定义Marshaller.请参阅有关如何实现这一目标的文档.

回答原始问题,为什么添加context =>会使请求超时:这是因为预定义指令已经是类型RequestContext => Unit.所以,写作

respondWithMediaType(`text/plain`) {
  complete("Hello World!")
}
Run Code Online (Sandbox Code Playgroud)

完全等同于(即自动扩展到)

ctx => respondWithMediaType(`text/plain`) {
  complete("Hello World!")
}.apply(ctx)
Run Code Online (Sandbox Code Playgroud)

因此,如果您只ctx =>手动添加,但不添加apply呼叫,则传入的请求永远不会进入内部路由,因此永远不会完成.编译器不会捕获此类错误,因为路由的类型是RequestContext => Unit,因此变量with和没有apply调用的变量都是有效的.我们将来会改进这一点.

有关如何构建路由的详细信息,请参阅文档.

最后,如果您需要提取标头或其值,您可以使用其中一个预定义的HeaderDirectives,它可以简化处理请求标头的过程.