All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.digitaltangible.playguard.XForwardedTrustImmediateConnectionRequestHandler.scala Maven / Gradle / Ivy

The newest version!
package com.digitaltangible.playguard

import java.net.InetAddress

import javax.inject.Inject
import play.api.http._
import play.api.mvc.request.RemoteConnection
import play.api.mvc.{EssentialFilter, Handler, Headers, RequestHeader}
import play.api.routing.Router
import play.core.DefaultWebCommands

import scala.util.Try

/**
 * Custom RequestHandler to replace the immediate connection with the last IP address in the X-Forwarded-For header, if available.
 * This is meant for scenarios where you don't know your immediate connection's IP address beforehand
 * (to configure it as a trusted proxy) but can still trust it, e.g. on Heroku.
 * Does not support RFC 7239.
 *
 * @param router
 * @param errorHandler
 * @param configuration
 * @param filters
 */
class XForwardedTrustImmediateConnectionRequestHandler @Inject()(
  router: Router,
  errorHandler: HttpErrorHandler,
  configuration: HttpConfiguration,
  filters: Seq[EssentialFilter]
) extends DefaultHttpRequestHandler(
      new DefaultWebCommands,
      None,
      router,
      errorHandler,
      configuration,
      filters
    )
    with HeaderNames {

  override def handlerForRequest(rh: RequestHeader): (RequestHeader, Handler) =
    super.handlerForRequest(rh.withConnection(getTrustedXForwardedFor(rh.headers) getOrElse rh.connection))

  private def getTrustedXForwardedFor(headers: Headers): Option[RemoteConnection] =
    for {
      lastForAddr <- h(headers, X_FORWARDED_FOR).lastOption
      inetAddr <- Try(InetAddress.getByName(lastForAddr)).toOption
      lastProtoO = h(headers, X_FORWARDED_PROTO).lastOption
    } yield RemoteConnection(inetAddr, lastProtoO.map(_.toLowerCase).contains("https"), None)

  private def h(h: Headers, key: String): Seq[String] =
    h.getAll(key).flatMap(s => s.split(",\\s*")).map(unquote)

  private def unquote(s: String): String =
    if (s.length >= 2 && s.charAt(0) == '"' && s.charAt(s.length - 1) == '"') {
      s.substring(1, s.length - 1)
    } else s
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy