2016-12-26 12 views
0

Использование Scala и Play 2.5.10 я реализовал следующие многоразовые действия для состава и с целью отключения кэширования в браузере, изменив заголовки ответа:Play 2.5.x Как изменить заголовки содержимого ответа, т. Е. Без кеша?

import play.api.http.HeaderNames 
import play.api.mvc._ 

import scala.concurrent.Future 
import scala.util.{Failure, Success} 
import scala.concurrent.ExecutionContext.Implicits.global 

case class NoCache[A](action: Action[A]) extends Action[A] with HeaderNames { 
    def apply(request: Request[A]): Future[Result] = { 
    action(request).andThen { 
     case Success(result) => result.withHeaders(
     (CACHE_CONTROL -> "no-cache, no-store, must-revalidate"), 
     (PRAGMA -> "no-cache"), 
     (EXPIRES -> "0") 
    ) 
     case Failure(result) => result 
    } 
    } 

    lazy val parser = action.parser 
} 

Я тогда повторно использовать его в своих реализациях действий контроллера, как это:

def link = NoCache { 
    deadbolt.SubjectPresent()() { implicit request => 
    Future { 
     Ok(views.html.account.link(userService, auth)) 
    } 
    } 
} 

I останова в NoCache реализации и она будет выполнена правильно, однако, используя Web Developer Firefox plugin для мониторинга сетевого трафика, я вижу, что заголовки ответа не содержат «нет кэша» модификации ... что Я делаю Неправильно?

+1

удалить 'andThen' и заменить его' map' – pamu

+1

Вот исправленный код 'случай класса NoCache [A] (действие: Действие [A]) распространяется действие [A] с HeaderNames { Защиту применить (запрос: Request [A]): ​​Future [Result] = { action (request) .map {result => result.withHeaders ( (CACHE_CONTROL -> "no-cache, no-store, must-revalidate"), (Прагма -> "нет кэша"), (EXPIRES -> "0") ) }} ленивых вал парсера = action.parser } ' – pamu

ответ

1

Проблема с кодом

проблема с andThen. andThen сбрасывает возвращаемое значение. Таким образом, преобразованный result с новыми заголовками отбрасывается.

Удалить andThen и сделать его map.

andThen Используется для выполнения побочных эффектов при вычислении сразу после завершения будущего, на которое он вызывается.

Вычисление andThen возвращает Будущее с тем же результатом, что и в оригинальном будущем, и отбрасывает возвращаемый тип вычисления внутри andThen.

Вот реализация andThen из стандартной библиотеки.

def andThen[U](pf: PartialFunction[Try[T], U])(implicit executor: ExecutionContext): Future[T] = { 
    val p = Promise[T]() 
    onComplete { 
     case r => try pf.applyOrElse[Try[T], Any](r, Predef.conforms[Try[T]]) finally p complete r 
    } 
    p.future 
    } 

исправляющие код

case class NoCache[A](action: Action[A]) extends Action[A] with HeaderNames { 
    def apply(request: Request[A]): Future[Result] = { 
    action(request).map { result => 
     result.withHeaders(
     (CACHE_CONTROL -> "no-cache, no-store, must-revalidate"), 
     (PRAGMA -> "no-cache"), 
     (EXPIRES -> "0") 
    ) 
    } 
    } 

    lazy val parser = action.parser 
} 

Другой способ сделать то же самое

Вы можете использовать Play фильтры Filter изменить заголовки, а также могут быть использованы для выполнения какой-то предварительно обработки и последующей обработки.

Вы можете настроить таргетинг только на определенные маршруты, проверив uri запроса.

import akka.stream.Materializer 
import com.google.inject.{Inject, Singleton} 
import play.api.http.DefaultHttpFilters 
import play.api.mvc.{Filter, RequestHeader, Result} 
import play.mvc.Http.HeaderNames 

import scala.concurrent.Future 

@Singleton 
class Filters @Inject() (fooFilter: FooFilter) extends DefaultHttpFilters(fooFilter) {} 

@Singleton 
class FooFilter @Inject() (implicit override val mat: Materializer) extends Filter { 
    override def apply(f: (RequestHeader) => Future[Result])(rh: RequestHeader): Future[Result] = { 
    f(rh).map { result => 
     if (rh.uri.startsWith("/foo")) 
     result.withHeaders(HeaderNames.CACHE_CONTROL -> "no-cache") 
     else result 
    } 
    } 
} 

В приведенном выше примере для /foo маршрута cache_control будет установлен и для других маршрутов того же заголовки будут распространяться.

Примечание создать фильтры внутри корневой папки приложения игры, если вы не имеете добавлять фильтры к application.conf

Никогда не запускать тяжелые бега вычисления внутри фильтров, сделать фильтры как можно более легким.

+0

Nice спасибо, но это вовсе не Ответьте на мой OP. Что не так с использованием композиции Action? и почему он не должен работать? проблема кажется больше на стороне withHeaders или что изменение ответа не распространяется правильно. Я по-прежнему предпочитаю использовать композицию Action, чтобы действительно увидеть, что происходит. –

+1

@ GiovanniAzua обновил ответ. pLease check – pamu

+1

@GiovanniAzua удалить 'andThen' и заменить его' map' – pamu