在我的Play 2.6应用程序中,我有一个自定义操作类,该类执行一些常见的操作,适用于我的所有操作。省略无关的细节,代码如下所示:
class VariantAction @Inject()
(parser: BodyParsers.Default)
(implicit ec: ExecutionContext)
extends ActionBuilderImpl(parser) with Results {
///
override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
if (aok) {
block(request).andThen {
case Success(result) =>
result.withHeaders("foo" -> "bar") // THIS DOES NOT WORK
case Failure(t) =>
}
}
catch {
/// Some exception handling
}
}
else {
Future.successful(ServiceUnavailable)
}
}
}
所有操作均按预期方式进行:andThen()中的回调已执行,但未添加尝试添加到响应中的标头。我想象有一个竞争条件,到回调被调用时,响应已经提交。当然,我可以将此逻辑添加到所有具体的操作中,但这似乎没有理由。
答案 0 :(得分:0)
构造block(request).andThen ...
仅返回一个result
,它不返回带有标头"foo"
的结果。也就是返回block(request)
的结果,而不是.andThen
的结果。 .andThen
中的回调最终将起作用,以为不会返回结果。
尝试将andThen
更改为map
。 andThen
用于“副作用”,“映射”用于“转换”结果。
这是区别:
您还需要确保在以后的操作中不要覆盖“ foo”标头。
答案 1 :(得分:0)
Andriy的答案包含了为什么我的代码无法正常工作的解释,但不是解决该问题的耗材答案:正如Andriy所指出的那样,问题的根源是我对Result.withHeaders()方法的误解:它不是可变器,而是产生一个新的Result对象。
这有效:
class VariantAction @Inject()
(parser: BodyParsers.Default)
(implicit ec: ExecutionContext)
extends ActionBuilderImpl(parser) with Results {
///
override def invokeBlock[A](request: Request[A], block: (Request[A]) => Future[Result]) = {
if (aok) {
block(request).map { _.withHeaders("foo" -> "bar") }
}
catch {
/// Some exception handling
}
}
else {
Future.successful(ServiceUnavailable)
}
}
}