如何在路由中匹配特定的接受头?

4

我希望创建一个路由,仅在客户端发送特定的Accept头部时匹配。我使用的是Spray1.2-20130822

我想让这个路由工作:

def receive = runRoute {
    get {
      path("") {
        accept("application/json") {
           complete(...)
        }
      }
    }
  }

这里我找到了一个使用accept()函数的规范,但是我不知道在我的Spray-Handler中导入什么才能使它作为指令工作。此外,我没有找到其他关于头部指令的文档,只有这些存根

2个回答

5
我会这样做:
def acceptOnly(mr: MediaRange*): Directive0 =
  extract(_.request.headers).flatMap[HNil] {
    case headers if headers.contains(Accept(mr)) ⇒ pass
    case _                                       ⇒ reject(MalformedHeaderRejection("Accept", s"Only the following media types are supported: ${mr.mkString(", ")}"))
  } & cancelAllRejections(ofType[MalformedHeaderRejection])

然后只需包装您的根节点:
path("") {
  get {
    acceptOnly(`application/json`) {
      session { creds ⇒
        complete(html.page(creds))
      }
    }
  }
}

顺便提一下,最新的喷雾器1.2夜间版是1.2-20130928,如果可以,请更新它。


这里有一个小错误:如果传入多个MediaRange并且没有匹配到任何一个,${mr: _*}的字符串插值会失败。如果我将其更改为${mr},它就可以运行,尽管输出现在包含了mr的类型,这可能不是预期的结果。 - rompetroll
2
@rompetroll 抱歉,不知道,谢谢。您可以用${mr.mkString(", ")}替换${mr: _*} - 4lex1v

2

没有预定义的指令叫做accept指令。您可以在此处查看可用指令的完整列表。

但是,您可以使用headerValueByName指令来创建一个自定义指令,以实现您所需的功能:

def accept(required: String) = headerValueByName("Accept").flatMap {
  case actual if actual.split(",").contains(required) => pass
  case _ => reject(MalformedHeaderRejection("Accept", "Accept must be equal to " + required))
}

将这段代码放在您的spray Route范围内,然后按照您在问题中展示的方式使用即可。


2
谢谢,那应该可以工作。虽然我可能应该将 if actual == required 更改为 if actual.split(",") 包含 required 或类似的内容。 - rompetroll

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接