Filters not working in Play 2.5.8

590 views
Skip to first unread message

Shailesh Tikhe

unread,
Oct 18, 2016, 11:36:48 AM10/18/16
to Play Framework
I am migrating play application from 2.4.6 to 2.5.8. I am stuck at using filters in play 2.5.X.
I have created RequestHandler which authenticates request and Filters which should apply filter to all responses.

Following are my entries in application.conf
play.http.requestHandler="utils.RequestHandler"
play
.http.filters="utils.Filters"


Following is my Filter.scala:

@Singleton
class Filters @Inject() (customFilter: CustomFilter) extends DefaultHttpFilters(customFilter)


@Singleton
class CustomFilter @Inject() (implicit val mat: Materializer) extends Filter {
 
def apply(nextFilter: RequestHeader => Future[Result])(requestHeader: RequestHeader): Future[Result] = {
    nextFilter
(requestHeader).map { result =>
      result
.withHeaders(
        PRAGMA
-> "no-cache",
        CACHE_CONTROL
-> "no-cache, no-store, must-revalidate, max-age=0",
        EXPIRES
-> serverTime
     
)
   
}
 
}
 
private def serverTime = { /* CODE */}
}


Following is my RequestHandler.scala

@Singleton
class RequestHandler @Inject() (router: Router) extends HttpRequestHandler {
 
def handlerForRequest(request: RequestHeader) = {
    router
.routes.lift(request) match {
     
case Some(handler) =>
        val response
= authenticate(request)
        response match
{
         
case Ok => (request, handler)
         
case Forbidden => (request, controllers.Application.forbidden)
         
case Unauthorized => (request, controllers.Application.unauthorized)
         
case _ => (request, controllers.Application.badRequest)
       
}
     
case None => (request, Action(Results.NotFound))
   
}
 
}
 
/* OTHER HELPER METHOD CODE*/
}

I am able to run play-application, however filter doesn't work(RequestHandler works correctly).

When I commented play.http.requestHandler="utils.RequestHandler" from application.conf, filters started working.

I tried more and observed that only one of RequestHandler and Filters works at a time.
Following is my observation:
1. Filter and RequestHandler are configured(Both are not in root package) -> Only Filter works
2. Only RequestHandler is configured(Filter present in root package) -> Only RequestHandler works
3. Only Filter is configured(RequestHandler present in root package) -> Only RequestHandler works
4. None of Filter and RequestHandler is configured(Both are present in root package) -> Only RequestHandler works

NOTE: Configured means I have entry in application.conf
I want to know what I am missing here.

Christian Schmitt

unread,
Oct 18, 2016, 12:53:55 PM10/18/16
to Play Framework

Shailesh Tikhe

unread,
Oct 19, 2016, 2:12:51 AM10/19/16
to Play Framework
I tried to extend DefaultHttpRequestHandler too. But still only RequestHandler is working.

Greg Methvin

unread,
Oct 19, 2016, 2:44:33 AM10/19/16
to play-framework
Without seeing your code we can only guess at what might be the problem here.  If you're extending DefaultHttpRequestHandler, the filters are applied inside the handlerForRequest method you're likely overriding: https://github.com/playframework/playframework/blob/2.5.x/framework/src/play/src/main/scala/play/api/http/HttpRequestHandler.scala#L139  So you need to either re-implement or delegate to that method, or find a way to achieve the same thing by overriding the other DefaultHttpRequestHandler methods.

Greg

--
You received this message because you are subscribed to the Google Groups "Play Framework" group.
To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/01b7dd47-21ff-4560-8d16-e6e416e43fe4%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.



--
Greg Methvin
Senior Software Engineer

Shailesh Tikhe

unread,
Oct 19, 2016, 11:28:15 AM10/19/16
to Play Framework
Hi Greg,

Following is my RequestHandler:

@Singleton
class HttpRequestHandler @Inject() (errorHandler: HttpErrorHandler, router: Router, configuration: HttpConfiguration, filter: Filters) extends DefaultHttpRequestHandler(router, errorHandler, configuration, filter) {
 
override def handlerForRequest(request: RequestHeader) = {

    router
.routes.lift(request) match {
     
case Some(handler) =>

       
Logger.info(s"Serving request: ${request.path} for ${request.method}")
       
(request, handler)

     
case None => (request, Action(Results.NotFound))
   
}
 
}
}


Following is my Filter:

@Singleton
class Filters @Inject() (customFilter: CustomFilter) extends DefaultHttpFilters(customFilter)


@Singleton
class CustomFilter @Inject() (implicit val mat: Materializer) extends Filter {
 
def apply(nextFilter: RequestHeader => Future[Result])(requestHeader: RequestHeader): Future[Result] = {
    nextFilter
(requestHeader).map { result =>
      result
.withHeaders(
        PRAGMA
-> "no-cache",
        CACHE_CONTROL
-> "no-cache, no-store, must-revalidate, max-age=0",
        EXPIRES
-> serverTime
     
)
   
}
 
}
 
private def serverTime = {

    val calendar
= Calendar.getInstance()
    val dateFormat
= new SimpleDateFormat(
     
"EEE, dd MMM yyyy HH:mm:ss z")
    dateFormat
.setTimeZone(calendar.getTimeZone)
    dateFormat
.format(calendar.getTime())
 
}
}


Following are entries in application.conf
play.http.requestHandler="utils.HttpRequestHandler"
play
.http.filters="utils.Filters"

I have also shared public copy of above code at: https://github.com/tikheshaileshn/play-2.5.8-upgrade

Can you please explain what am I doing wrong here?
To unsubscribe from this group and stop receiving emails from it, send an email to play-framewor...@googlegroups.com.

Greg Methvin

unread,
Oct 19, 2016, 2:11:49 PM10/19/16
to play-framework
You are injecting Filters into your HttpRequestHandler but aren't doing anything with them in handlerForRequest. So basically it's the problem I just described in my last comment.

To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/d437655a-80ac-487f-859e-619415841aed%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

sti...@intelli-vision.com

unread,
Oct 20, 2016, 2:44:14 AM10/20/16
to Play Framework
Hi Greg,
Thank you for pointing out my mistake.
I have followed play documentation to implement RequestHandler: https://www.playframework.com/documentation/2.5.x/ScalaHttpRequestHandlers#extending-the-default-request-handler
It doesn't say anything about using filters in RequestHandler.
Can you please explain how can I use filters to modify response header in RequestHandler?
One more question I have is when I don't create RequestHeader, play 2.5.X applies Filters. As soon as I create RequestHandler, Filters stop working. Why is it so?

Greg Methvin

unread,
Oct 20, 2016, 3:05:36 AM10/20/16
to play-framework
Filters are applied by DefaultHttpRequestHandler within the handlerForRequest method: https://github.com/playframework/playframework/blob/2.5.x/framework/src/play/src/main/scala/play/api/http/HttpRequestHandler.scala#L139

So obviously if you override that method, you'll be responsible for making filters work. That's the cost of using this low-level abstraction. You can copy, modify, or extend the code from DefaultHttpRequestHandler's handlerForRequest, or you can try to achieve the same thing by overriding another method, for example routeRequest:

override def routeRequest(request: RequestHeader) = {
  val maybeHandler = super.routeRequest(request)
  if (maybeHandler.isDefined) {
    log.info(s"Serving request: ${request.method} ${request.path}")
  }
  maybeHandler
}

To unsubscribe from this group and stop receiving emails from it, send an email to play-framework+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/play-framework/47d587cd-5c0e-4559-ae4d-7acbb34d47ca%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Shailesh Tikhe

unread,
Oct 20, 2016, 3:55:14 AM10/20/16
to Play Framework
Thank you so so much, Greg!
I referred https://github.com/playframework/playframework/blob/2.5.x/framework/src/play/src/main/scala/play/api/http/HttpRequestHandler.scala#L139 and changed my return statement form (request, result) to (request, filterHandler(rh => handler)(request)). This works for me.
Message has been deleted

Sreenivasulu Nallapati

unread,
Nov 18, 2016, 7:25:13 AM11/18/16
to Play Framework
Hello Shailesh,
How  this code((request, filterHandler(rh => handler)(request))) is working for you? I see filterHandler method is a protected method in the HttpRequestHandler.scala

Thanks
Sreenivasulu
Reply all
Reply to author
Forward
0 new messages