Search code examples
scalagoogle-app-enginehttpsplayframeworkapp-engine-flexible

Redirect HTTP requests to HTTPS on Google App Engine and Play Framework


I'm using flexible environment on Google App Engine to run web app written in Scala and Play Framework. I've added custom domain to my application and now my app is available both through http and https. But I need to make redirection from http to https. I've tried to manage it by doing the following, but it didn't work:

application.conf:

play.http.filters = "controllers.Filters"

controllers.Filters:

import javax.inject.Inject

import play.api.http.DefaultHttpFilters
import play.filters.cors.CORSFilter
import play.filters.https.RedirectHttpsFilter

class Filters @Inject() (corsFilter: CORSFilter, redirectHttpsFilter: RedirectHttpsFilter) extends DefaultHttpFilters(corsFilter, redirectHttpsFilter)

UPD Maybe the problem is that I need to specify https port in my Dockerfile? Here is a Dockerfile:

FROM gcr.io/google_appengine/openjdk
RUN wget http://downloads.lightbend.com/scala/2.11.8/scala-2.11.8.deb
RUN dpkg -i scala-2.11.8.deb
RUN wget https://dl.bintray.com/sbt/debian/sbt-0.13.13.deb
RUN dpkg -i sbt-0.13.13.deb
RUN apt-get update
RUN apt-get install scala sbt
RUN rm -f scala-2.11.8.deb
RUN rm -f sbt-0.13.13.deb
ADD . /appname
WORKDIR /appname
RUN chmod 755 ./docker-entrypoint.bash
ENTRYPOINT ["./docker-entrypoint.bash"]
CMD ["./target/universal/stage/bin/appname", "-Dhttp.port=8080"]

Solution

  • Here is how I achieved what I wanted:

    class Filters @Inject() (corsFilter: CORSFilter, redirectHttpsFilter: HttpsFilter)
                         extends DefaultHttpFilters(corsFilter, redirectHttpsFilter)
    
    @Singleton
    class HttpsFilter extends EssentialFilter {
    
      override def apply(next: EssentialAction): EssentialAction =  EssentialAction { req =>
        req.headers.get("X-Forwarded-Proto") match {
          case Some("http") =>
            //Got request over HTTP
            val httpsUrl = s"https://${req.host}"
            Accumulator.done(Results.Redirect(httpsUrl))
          case _ =>
            next(req)
        }
      }
    }
    

    application.conf:

    play.http.filters = "controllers.Filters"