playframework/Play20 — pull request #1326 by bwbecker (2013-07-10 16:37:00+00:00)
Title: Add isHttps to RequestHeader

I've added a new data item to RequestHeader, isHttps. It's true if the request is the result of https://... and false for http://...

It's suggested in https://groups.google.com/forum/?fromgroups=#!topic/play-framework/XDOspUJhdX4 where Alex Jarvis said "I think that it would be great to have a 'secure' flag in the request object, when the app server knows the request is secure (not saying that I personally need this anymore, but if especially if the app server is doing the SSL, then why not). There must have some forethought before adding it to Play 1."

James Roper replied "We could add it, it's probably a bit late in 2.1 though to do it."

I needed this functionality (I think!) to implement an interceptor to redirect all http requests to https. I realize (now) that I could have done this with a front-end proxy server but was already almost all the way with just using Play by itself. So anyway, with the changes, I can put the following in the Global class to redirect http to https:

object Global extends WithFilters(HttpsCheck) {...}

object HttpsCheck extends Filter with Results {
override def apply(next:RequestHeader => Result)(request:RequestHeader):Result = {
if (!request.isHttps) {
val url = s"https://${request.host.replaceFirst("9000", "9443")}${request.uri}"
Logger.debug("Redirecting to " + url)
Redirect(url, request.queryString, play.api.http.Status.SEE_OTHER)
}
else next(request)
}
}

My approach was to set the isHttps flag true if Netty's pipeline has an SslHander in it (see PlayDefaultUpstreamHandler.scala). It would be useful for a Netty expert to confirm that is a correct assumption.

All the tests that used to pass still pass. I've added a trivial test. I'd be happy to add more robust tests if someone can coach me on the basic approach.