2015-12-07 4 views
3

Согласно play documentation этого является то, что пользовательские действия должны выглядеть следующим образом:Play 2.4: перехватывать и изменять тело ответа

object CustomAction extends ActionBuilder[Request] { 
    def invokeBlock[A](request: Request[A], block: Request[A] => Future[Result]): Future[Result] = { 
     block(request) 
    } 
} 

Но сказать, если бы я хотел добавить «Foo» для каждого тела ответа, как мне делать что? Очевидно, что ниже не работает:

block.andThen(result => result.map(r => r.body.toString + "foo")).apply(request) 

Любые идеи?

UPDATE: Что-то стоит отметить, что это действие будет в основном используется как асинхронный в контроллере:

def test = CustomAction.async { 
    //... 
} 

ответ

2

Вы должны будете принять Enumerator[Array[Byte]] от Result тела и кормить его к iteratee для фактического потребления тела результата, прежде чем вы сможете его изменить. Таким образом, простой iteratee, который потребляет результирующее тело и преобразует в строку может выглядеть следующим образом:

block.apply(request).flatMap { res => 
    Iteratee.flatten(res.body |>> Iteratee.consume[Array[Byte]]()).run.map { byteArray => 
    val bodyStr = new String(byteArray.map(_.toChar)) 
    Ok(bodyStr + "foo") 
    } 
} 

Я использовал flatMap в результате запуска Iteratee.flatten является Future[T]. Зайдите в https://www.playframework.com/documentation/2.4.x/Enumerators для получения дополнительной информации о том, как работать с Enumerators/Iteratees.

+0

Спасибо, это работает, однако есть одна проблема - решение по умолчанию «ОК» и переопределит другие типы ответов, такие как «BadRequest» – Caballero

+0

. Мой пример должен был быть простым, чтобы сделать его более полным, вам нужно будет прочитайте статус результата из ResponseHeader и соответствующим образом обработайте новый результат – josephpconley

Смежные вопросы