gpt4 book ai didi

scala - Spray:如何将 respondWithHeaders 应用于所有路线而不是每个路线

转载 作者:行者123 更新时间:2023-12-02 07:29:57 25 4
gpt4 key购买 nike

我正在学习 Scala,但还不熟悉使用 Spray 框架构建一些 REST-API 应用程序并面临这个问题:我所有的 HTTP 响应都应该有特定的 header (Access-Control-Allow-Origin)。所以我找不到如何将它设置为一次所有应用程序的响应,而不是每个响应。

我的路线是这样的:

trait Statistics extends HttpService { self: StatisticModuleLike =>

implicit def MM: MarshallerM[Future]

lazy val statisticsRoute =
path("statistics" / "applications" / Segment / Segment ) { (measure, period) =>
get {
respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*")) {
complete {
getAppCount(MeasureType.withName(measure), period.toInt)
}
}
}
} ~
path("statistics" / "approvals" / Segment / Segment ) { (measure, period) =>
get {
respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*")) {
complete {
getApproval(MeasureType.withName(measure), period.toInt)
}
}
}
} ~
path("statistics" / "amounts" / Segment / Segment ) { (measure, period) =>
get {
respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*")) {
complete {
getAmount(MeasureType.withName(measure), period.toInt)
}
}
}
} ~
path("statistics" / "sellers" / "snooze") {
get {
respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*")) {
complete {
getSellerSnooze(MeasureType.withName("Month"), 100)
}
}
}
} ~
path("statistics" / "sellers" / "snooze" / Segment / Segment ) { (measure, period) =>
get {
respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*")) {
complete {
getSellerSnooze(MeasureType.withName(measure), period.toInt)
}
}
}
} ~
path("statistics" / "sellers" / "growing" / Segment / Segment ) { (measure, period) =>
get {
parameter('percent.as[Int] ? 0) { percent =>
respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*")) {
complete {
getSellerDynamic(MeasureType.withName(measure), period.toInt, DynamicTrendType.withName("Growing"), percent)
}
}
}
}
} ~
path("statistics" / "sellers" / "falling" / Segment / Segment ) { (measure, period) =>
get {
parameters('percent.as[Int] ? 0, 'average.as[Int] ? 0) { (percent, average) =>
respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*")) {
complete {
getSellerDynamic(MeasureType.withName(measure), period.toInt, DynamicTrendType.withName("Falling"), percent)
}
}
}
}
}
}

如你所见,添加

respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*"))

每条路都不方便...

有什么好的方法可以解决这个问题吗?比如说,通过一些定制来扩展 HttpService 并使用它而不是基础服务?

最佳答案

那是一条大路 =)。实际上 spray 指令是完全可组合的,因此不需要重复,您可以将结构简化为如下所示:

respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*")) {
(pathPrefix("statistics") & get) {
pathPrefix("applications") {
path(Segment / Segment) { (measure, period) =>
complete { getAppCount(MeasureType.withName(measure), period.toInt) }
}
} ~
pathPrefix("applications") { ... } ~
path("amounts") { ... } ~
...
}
}

其中 PathPrefix 检查路径是否以给定前缀开头,Path 简单匹配路由的其余部分,还有 pathSuffix、pathEnd 等...

此外,为了简化大型结构,我发现将 Spray 与 Cake Pattern 组合在一起并制作所谓的 Handlers 非常有用,它可以处理您的逻辑,此解决方案更灵活且更易于测试:

trait SprayRoute extends CounterHandler with ... {
val service: Route = {
respondWithHeader(RawHeader("Access-Control-Allow-Origin", "*")) {
(pathPrefix("statistics") & get) {
pathPrefix("applications") {
path(Segment / Segment) { CounterHandler }
} ~
pathPrefix("applications") { ... } ~
path("amounts") { ... } ~
...
}
}
}
}

trait CounterHandler {
def CounterHandler: (String, String) => Route = { (measure, period) =>
complete { getAppCount(MeasureType.withName(measure), period.toInt) }
}
}

关于scala - Spray:如何将 respondWithHeaders 应用于所有路线而不是每个路线,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23007581/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com