我通過覆蓋GlobalSettings的onRouteRequest方法攔截所有對我的應用程序的請求。現在,我需要從這裏發送一些數據到已發送的動作,以便在所有動作中不執行所有這些計算。如何將屬性設置爲傳遞給super onRouteRequest方法的請求(play.api.mvc.RequestHeader)對象?如何在PlayFramework中將變量傳遞給攔截請求中的Action?
回答
您的需求,我使用onRouteRequest
將工作(優雅至少)沒有的事。
但是,讓我們嘗試使用一個專用的結構進行攔截。
這裏是你如何能攔截請求,計算一些通用的東西,並把它傳遞給行動
首先,這裏是有一個方法intercept
和便利的方法username
的Interceptor
對象:
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"))
}
正如你可以看到,工人功能intercept
讓您有機會來計算基於請求內容的一些東西。 B
類型的哪一個計算結果可能失敗(Option
),在那種情況下,處理程序在那裏告訴做什麼。
定義了要計算的內容後,您可以使用一個函數來定義您的action
,該函數採用B
並給出Action[A]
。
的username
方法只是一個簡單的預定義的攔截器,可以使我們能夠定義如何獲取登錄的用戶名,只是爲了說明。
現在這裏是我們如何能夠在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))
}
}
使用這兩者現在,如果你有一個通用的計算,你可以創建預先配置的攔截器(在這裏我使用的情況下階層,而是簡單地定義這部分應用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)
}
}
相關注釋編輯:
因此您的意見,這裏是你如何能使用攔截器(請注意,我嘲笑了主機檢索和檢查)
使用hosted
和anotherHosted
,你就可以測試這個流程做:
- /託管/假?主機=爲myhost => 404,因爲在第一次爲myhost是不緩存和我提供了虛假的檢查樣機
- /託管/真的嗎?主機=爲myhost =>不在緩存中,但它會添加它,然後沒有404
- /託管/ anotherHosted /假?主機=爲myhost =>在緩存中,因爲它託管=>無404
- /託管/ anotherHosted /假?主機= notMyhost => 404
下面是代碼
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)
}
}
謝謝Andy,讓我告訴你確切的情況下,我正在構建一個託管應用程序,用戶可以註冊並映射其域名。當他們的用戶/客戶碰到他們的映射域時,它首先檢查域是由我們託管還是返回404錯誤。如果該域名是託管的,我想將網站信息傳遞給所有的操作,以便我不在其中再次獲取它。 – Aman
- 1. 如何將變量傳遞給Action?
- 2. 如何在Python中將變量傳遞給輸入請求?
- 3. 將變量傳遞給ajax請求jquery
- 4. 將JavaScript變量傳遞給JSON請求
- 5. 如何攔截Perl中的HTTP請求?
- 6. 如何攔截C#中的http請求?
- 7. 如何攔截IIS中的WCF請求
- 8. JEE:如何參數傳遞給攔截
- 9. 傳遞參數給攔截
- 10. 將參數傳遞給bytebuddy攔截器
- 11. Selenium:如何攔截請求
- 12. 在發送請求和/或回覆之前將數據傳遞給攔截器
- 13. 如何將數組從Ajax請求傳遞給Javascript變量
- 14. 攔截不存在的Playframework /地址的網絡請求
- 15. 在action中傳遞變量值url
- 16. 攔截a4j:commandButton請求
- 17. 攔截WEBrick請求
- 18. 攔截傳出的HTTP請求
- 19. Ninject攔截屬性的參數傳遞給攔截器?
- 20. 在Ajax請求後將變量傳遞給回調
- 21. 攔截之前:在請求
- 22. 在JavaScript中攔截HTTP請求
- 23. 在WebView中攔截「file:」方案請求
- 24. 在as3中攔截加載器請求
- 25. 在ASP.NET MVC框架中攔截請求
- 26. 如何JavaScript變量傳遞給jQuery的Ajax請求
- 27. Unity攔截:如何將參數傳遞給ICallHandler實現?
- 28. 如何攔截webservicehost的請求
- 29. 將過期的會話變量值傳遞給後續請求
- 30. 如何將JButton傳遞給Action Listener類
設置的屬性不可用,因爲在功能性,我們是在一個不變的環境。因此,例如在會話中添加東西時,您可以使用'withSession'創建一個「新的東西」。並且在onRouteRequest的背景下,您無法創建新的請求,因爲您無法將此新內容添加到您的基礎操作 –
+100,同一條船上,有一個數據片段以注入適用於ALL路線/操作的請求-types。我想在一個地方進行數據計算,onRouteRequest,然後在應用程序中的任何地方隱式請求在範圍內,可以訪問數據(而不是在不同的地方重新計算它,或者爲每個Action添加樣板來處理它)。 – virtualeyes
@andypetrella scala並非純粹的功能。我們可以將數據注入到通過操作組合和WrappedRequest的請求中,從而有效修改請求後路由。我會非常喜歡佔位符Map [String,String]在onRouteRequest中設置。您可以複製請求,例如爲RequestHeader上的「標籤」映射賦值。玩當然,吹走你的寶貴數據,使用標籤地圖路由結果(控制器方法,類型GET等) – virtualeyes