无法在ActionBuilderImpl.invokeBlock()中附加响应标头

时间:2019-01-28 06:21:33

标签: scala playframework playframework-2.6

在我的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()中的回调已执行,但未添加尝试添加到响应中的标头。我想象有一个竞争条件,到回调被调用时,响应已经提交。当然,我可以将此逻辑添加到所有具体的操作中,但这似乎没有理由。

2 个答案:

答案 0 :(得分:0)

构造block(request).andThen ...仅返回一个result,它不返回带有标头"foo"的结果。也就是返回block(request)的结果,而不是.andThen的结果。 .andThen中的回调最终将起作用,以为不会返回结果。

尝试将andThen更改为mapandThen用于“副作用”,“映射”用于“转换”结果。

这是区别:

enter image description here

您还需要确保在以后的操作中不要覆盖“ 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)
      }
   }
}