Estoy interceptando todas las solicitudes en mi aplicación de juego anulando el método onRouteRequest de GlobalSettings. Ahora, necesito enviar algunos datos a la acción enviada desde aquí para que no realice todos esos cálculos en todas las acciones. ¿Cómo configuro un atributo para el objeto request (play.api.mvc.RequestHeader) que paso al método super onRouteRequest?¿Cómo pasar una variable a una Acción desde una solicitud interceptada en PlayFramework?
Respuesta
Para su necesidad, no creo que el onRouteRequest
funcione (elegantemente al menos).
Pero intentemos usar una estructura dedicada para interceptar.
Aquí es cómo se puede interceptar la petición, calcular algunas cosas genéricas y pasarlo a la acción
En primer lugar, aquí es un objeto Interceptor
que tiene un método intercept
y un método conveniente username
:
object Interceptor {
def intercept[A, B](f: RequestHeader => Option[B], e: RequestHeader => Result)(action: B => Action[A]): Action[(Action[A], A)] = {
val bodyParser = BodyParser {
request =>
f(request) map {
b =>
val innerAction = action(b)
innerAction.parser(request).mapDone {
body => body.right.map(innerBody => (innerAction, innerBody))
}
} getOrElse {
Done(Left(e(request)), Input.Empty)
}
}
Action(bodyParser) {
request =>
val (innerAction, innerBody) = request.body
innerAction(request.map(_ => innerBody))
}
}
def username[A](check: RequestHeader => Option[String]): ((String) => Action[A]) => Action[(Action[A], A)] = intercept(check, r => Results.Unauthorized("not logged in"))
}
Como puede ver, la función de trabajador intercept
le da la oportunidad de calcular algunas cosas en función del contenido de la solicitud. Qué resultado de cálculo del tipo B
podría fallar (Option
), en ese caso, un controlador está allí para decir qué hacer.
Tener definido qué calcular, puede definir su action
usando una función que toma un B
y da un Action[A]
.
El método username
es simplemente un simple interceptor predefinido que nos permite definir cómo recuperar el nombre de usuario registrado, solo para ilustrarlo.
Ahora aquí es cómo podemos utilizar los dos en su Controller
//index is defined for both GET and POST in routes, but fails on POST
// thanks to the interceptor that checks at first the used method
// the case mustn't be handled in the Action definition
def index = Interceptor.intercept(
/*check the method*/
request => if (request.method == "GET") Some(request.method) else None,
/*not a GET => bad request*/
request => BadRequest(request.method + " not allowed")
) { /*the computation result*/method => Action {
Ok("The method : " + method)
}
}
//this controller retrieve the username in the session and renders it in a OK response
def secured = Interceptor.username(r => r.session.get("username")) { username => Action {
Ok("You're logged in as " + username)
}
}
//this enables you to logged in => store in session
def login(u:String) = Action { request => {
Ok("Logged in as " + u) withSession(("username" -> u))
}
}
Ahora bien, si usted tiene un cálculo genérico puede crear su interceptor preconfigurado (en este caso estoy usando una clase de caso, sino simplemente definir una función que se aplica parcialmente el interceptor
es suficiente)
case class Intercept[B] (f: RequestHeader => Option[B], e: RequestHeader => Result) {
def apply[A](action: B => Action[A]) = Interceptor.intercept[A,B](f, e)(action)
}
val getInterceptor = Intercept[String](
request => if (request.method == "GET") Some(request.method) else None,
request => BadRequest(request.method + " not allowed")
)
def index2 = getInterceptor { method => Action {
Ok("Da method : " + method)
}
}
EDITAR relacionado con el comentario:
consecuencia de su comentario, aquí es cómo se puede hacer usando un interceptor (tenga en cuenta que he burlado hasta la recuperación de acogida y la comprobación)
Usando hosted
y anotherHosted
, podrás poner a prueba este flujo de trabajo:
- /alojada/falso? host = myhost => 404 porque al principio myhost no se almacena en caché y he proporcionado falsa a la maqueta comprobado
- /alojada/verdad? host = myhost => no en caché, pero lo hará agréguelo, y luego no 404
- /hosted/anotherHosted/false? host = myhost => en caché porque está alojado => no 404
- /hosted/anotherHosted/false?host = notMyhost => 404
Este es el código
def getHost(request:RequestHeader) = request.queryString.get("host").get.head
def checkHost(host:String, b: Boolean) = b
val checkHosted = (b: Boolean) => Intercept[String](
request => {
val host = getHost(request)
Cache.getAs[String](host) match {
case [email protected](_) => x
case None => if (checkHost(host, b)) {
Cache.set(host, host)
Some(host)
} else None
}
},
request => NotFound(getHost(request) + "not hosted")
)
def hosted(b:String) = checkHosted(b.toBoolean) {
host => Action {
Ok("this host is ok : " + host)
}
}
def anotherHosted(b:String) = checkHosted(b.toBoolean) {
host => Action {
Ok("this host is ok : " + host)
}
}
Gracias Andy, déjame decirte el escenario exacto, estoy construyendo una aplicación alojada a la cual los usuarios pueden registrarse y asignar su dominio. Cuando sus usuarios/clientes llegan a su dominio mapeado, primero verifica si el dominio está alojado por nosotros o devuelve un error 404. Si el dominio está alojado, quiero pasar la información del sitio a todas las acciones, para que no vuelva a buscarlo en ellas. – Aman
- 1. cómo pasar una variable a una acción UIButton
- 2. ¿Cómo pasar una variable a form_theme?
- 3. Cómo pasar una colección/parámetros de matriz a una Acción
- 4. ¿Cómo pasar una variable a una etiqueta personalizada en Liquid?
- 5. ¿Cómo pasar una variable Bash a Python?
- 6. cómo pasar una variable a otra rosca
- 7. pasar una variable a una URL activo Assetic en Symfony2
- 8. ¿Cómo pasar una variable de settings.py a una vista?
- 9. ¿cómo puedo pasar una variable a una nueva declaración Runnable?
- 10. PHP - Cómo pasar una variable global a una función
- 11. Pasar una variable local de una función a otra
- 12. Pasar una variable URL a xsl
- 13. pasar una variable booleana opcional
- 14. Pasar una variable por referencia a una extensión PHP
- 15. pasar grep en una variable en bash
- 16. Pasar valores a una solicitud PUT JSON en C#
- 17. cómo pasar una variable con redirect_to?
- 18. ¿Cómo puedo pasar una matriz de const o una matriz variable a una función en C?
- 19. ¿Cómo puedo pasar una estética ggplot2 de una variable?
- 20. Pasar una variable en redirección en Django
- 21. pasar una variable en un disparador
- 22. ¿Cómo pasar una variable de PHP a LESS?
- 23. ¿Cómo pasar fácilmente una variable a un archivo .sass?
- 24. Pasar objetos anónimos desde una vista a una vista parcial
- 25. ¿Cómo enviar una solicitud GET desde PHP?
- 26. Pasar una variable a la plantilla en Middleman 2
- 27. C# - ¿Cómo puedo pasar una referencia a una función que requiere una variable de salida?
- 28. variable de pasar a una macro en Jinja2
- 29. pasar una variable a partir de afeitar cshtml a jQuery
- 30. ¿Cómo hacer una solicitud HTTP desde SSIS?
Configuración de un atributo no está disponible debido a que en funcional, estamos en un entorno inmutable. De modo que, al agregar cosas a la sesión, por ejemplo, se crea "una nueva" con 'withSession'. Y en el contexto de onRouteRequest no puede crear una nueva solicitud porque no podrá dar esta nueva a su acción subyacente –
+100, misma embarcación, tiene un fragmento de datos para inyectar en la Solicitud que se aplica a TODAS las rutas/acciones -Tipos. Me gustaría hacer el cálculo de los datos en un solo lugar, onRouteRequest, y luego en cualquier lugar de la aplicación donde una solicitud implícita esté en el alcance, tenga acceso a los datos (frente a refinanciarlos, calcificándolos en varios lugares o añadiendo repetitivo para cada acción para manejarlo). – virtualeyes
@andypetrella scala no es puramente funcional. Podemos inyectar datos en la solicitud a través de la composición de acción y WrappedRequest, modificando efectivamente la solicitud posterior a la ruta. Me encantaría un marcador de posición Map [String, String] para establecer en onRouteRequest. Puede copiar la solicitud y, por ejemplo, dar un valor al Mapa de "etiquetas" en el RequestHeader. Jugar, por supuesto, soplo sus datos preciosos, usando las etiquetas Mapa para los resultados de enrutamiento (método del controlador, tipo GET, etc.) – virtualeyes