Play には CSRF 対策を行う CSRFFilter や、GZip 圧縮のための GzipFilter が用意されている。これらの Filter を特定の path にだけ(もしくは特定の path を除いて)適用したかったので、ちょっとしたクラスを作った。
FilterOnly.scala
import play.api.mvc.{ RequestHeader, EssentialAction, EssentialFilter }
/**
* Apply underlying filter only when f returns true.
*/
class FilterOnly(underlying: EssentialFilter, f: RequestHeader => Boolean) extends EssentialFilter {
override def apply(next: EssentialAction): EssentialAction = new EssentialAction {
private[this] val filteredNext = underlying(next)
override def apply(rh: RequestHeader) = if (f(rh)) filteredNext(rh) else next(rh)
}
}
object FilterOnly {
implicit class EssentialFilterFilterOnlyImplicit(val filter: EssentialFilter) extends AnyVal {
def only(f: RequestHeader => Boolean) = new FilterOnly(filter, f)
}
}
import FilterOnly._
とすれば CSRFFilter().only(_.path.startWith("/target"))
というふうに、特定の path にだけ適用する Filter を既存の Filter から作れる。
only()
に渡す関数の引数は RequestHeader
なので、path 以外にもヘッダ情報をみて適用するか否かの判断をすることもできる。
きっと同じようなコードがどこかにありそうな気がするが、見つけられなかったので晒しておく。