How to transfer a variable to an action from an intercepted request in PlayFramework?

I intercept all requests to my game application by overriding the onRouteRequest method for GlobalSettings. Now I need to send some data to the posted action from here, so that I do not perform all these calculations in all actions. How to set the request object attribute (play.api.mvc.RequestHeader) that I pass to the super onRouteRequest method?

+6
source share
1 answer

For your need, I do not use onRouteRequest to work (at least elegantly).

But try using a dedicated structure to intercept.

Here is how you can intercept the request, calculate some common material and pass it to Action

First of all, here is an Interceptor object that has an intercept method and a convenient username method:

 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")) } 

As you can see, the intercept working function gives you the ability to calculate some materials based on the contents of the query. What type B result may fail ( Option ), in which case the handler must tell what to do.

Having defined what to calculate, you can define your action using a function that takes B and gives Action[A] .

The username method is just a predefined hook that allows us to determine how to get a registered username, just for illustration.

Now here is how we can use both of them in your 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)) } } 

Now, if you have a general calculation, you can create your own preconfigured interceptor (here I use the case class, but just define a function that partially uses the Interceptor )

  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) } } 

EDIT related to comment:

According to your comment, here is how you could use an interceptor (note that I mocked about finding and checking the host)

Using hosted and anotherHosted , you can test this workflow:

  • / hosting / false? host = myhost => 404, because at first myhost is not cached, and I provided false to the verified layout
  • / hosting / true? host = myhost => is not in the cache, but it will add it and then no 404
  • / hosting / anotherHosted / false? host = myhost => in the cache because it is located => no 404
  • / hosting / anotherHosted / false? host = notMyhost => 404

Here is the code

 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 x@Some (_) => 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) } } 
+2
source

Source: https://habr.com/ru/post/917707/


All Articles