Pergunta

I'm trying to craft a ScalaInterceptor that looks for an X-Forwarded-Proto header, so basically if its in production or behind a proxy then Play! auto redirects to SSL.

I've run into issues with getting this code to compile, and I'm also not sure whether this will work with the SecureSocial plugin. There are specific reasons why we aren't setting SSL=true in SecureSocial.conf that I won't go into here.

Here's what I have in my Global.scala

  def WithHttpsRedirect[A](action: Action[A]): Action[A] = {
    Action(action.parser) { request =>
      val result = action(request)
      request.headers.get("X-Forwarded-Proto").collect {
        case "https" =>
          result

        case "http" =>
          val url = "https://"+request.host+request.uri
          Redirect(url)

      } getOrElse {
        result
      }
    }
  }

  override def onRouteRequest(request: RequestHeader): Option[Handler] = {
    super.onRouteRequest(request).map { handler =>
      handler match {
        case a: Action[_] => WithHttpsRedirect(a)
        case _ => handler
      }
    }
  }

I'm getting a compiler error after the getOrElse:

[error]  found   : scala.concurrent.Future[play.api.mvc.SimpleResult]
[error]  required: play.api.mvc.Result
[error]         result
[error]         ^

Your help is greatly appreciated!

Foi útil?

Solução 2

Changed my method of attack, and instead implemented a filter instead of overriding onRouteRequest:

In Global.scala:

object Global extends WithFilters(HttpsFilter) with GlobalSettings

then HttpsFilter.scala:

import play.api.mvc.Results._
import play.api.mvc.{SimpleResult, RequestHeader, Filter}
import scala.concurrent._
import ExecutionContext.Implicits.global

object HttpsFilter extends Filter {

  def apply(next: (RequestHeader) => Future[SimpleResult])(request: RequestHeader): Future[SimpleResult] = {
    request.headers.get("X-Forwarded-Proto").collect {
      case "https" =>
        next(request)

      case "http" =>
        val url = "https://"+request.host+request.uri
        Future{ Redirect(url) }

    } getOrElse {
      next(request)
    }
  }

}

Outras dicas

Replace:

Action(action.parser) { request =>

with:

Action.async(action.parser) { request =>

You made need to also replace:

Redirect(url)

with:

Future.successful(Redirect(url))
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top