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