java - Play Framework Multi-Tenant Filter
scala playframework (1)
Estoy intentando crear una aplicación multi-tenant utilizando Play Framework 2.2 y me he encontrado con un problema. Quiero establecer una clave de sesión en el onRouteRequest
global (o onRequest
en Java) que identifica el ID del sitio para el dominio que el usuario está solicitando. En literalmente docenas de otros marcos este tipo de cosas son indoloras (por ejemplo, Django), pero estoy aprendiendo que el objeto de sesión en Play es aparentemente inmutable, sin embargo.
Entonces, ahora mismo, tengo algo como esto:
override def onRouteRequest(request: RequestHeader): Option[Handler] = {
if (request.session.get("site").isEmpty){
val id = models.Site.getSiteUIDFromURL(request.host.toLowerCase()).toString()
if (!id.isEmpty){
//what goes here to set the session?
}else{
//not found - redirect to a general notFound page
}
}
super.onRouteRequest(request)
}
Y, aunque no es la forma más eficiente de usar una búsqueda en la base de datos, funciona para las pruebas en este momento. Necesito poder establecer una clave de sesión en el mundo, pero estoy completamente perdido en cómo hacerlo. Si hay algún método mejor, soy todo oídos (¿tal vez envolviendo mis controladores?).
Estoy abierto a ejemplos de soluciones en Java o Scala.
Piense en las acciones en Play como llamadas a funciones, la entrada es la solicitud, la salida es el resultado. Si desea cambiar el resultado de una llamada de función envuelta, primero debe invocar la función y luego aplicar su cambio. Agregar una clave a una sesión está cambiando el resultado, ya que la sesión se envía al cliente en la cookie de sesión. En el código anterior, intenta hacer el cambio antes de que tenga un resultado para cambiar, es decir, antes de llamar a super.onRouteRequest
.
Si no necesita modificar en absoluto el enrutamiento, no haga esto en onRouteRequest
, hágalo en un filtro, mucho más fácil allí. Pero suponiendo que necesita modificar el enrutamiento, entonces necesita aplicar un filtro al controlador devuelto. Esto es lo que podría parecer:
override def onRouteRequest(request: RequestHeader): Option[Handler] = {
val maybeSite: Option[String] = request.session.get("site").orElse {
// Let''s just assume that getSiteUIDFromUrl returns Option[String], always use Option if you''re returning values that might not exist.
models.Site.getSiteUIDFromURL(request.host.toLowerCase())
}
maybeSite.flatMap { site =>
super.onRouteRequest(request).map {
case e: EssentialAction => EssentialAction { req =>
e(req).map(_.withSession("site" -> site))
}
case other => other
}
}
}
Compruebe el código fuente del CSRFFilter para ver ejemplos de cómo agregar cosas a la sesión en un filtro.