Tomcat + Play framework 讀不到POST的資料 « Terrence的宅宅幻想
最近在進行的play framework部署到tomcat上執行所遇到的問題
這裡記錄一下問題發生狀況
部署方法:將play framework application打包成war之後放到tomcat上執行
開始只有tomcat+play的時候還執行的蠻順利的
之後加上tomcat的servlet filter之後出現play讀取不到post data的狀況
但是使用spring等卻不會有此問題
會加上filter是因為正式環境上通常會有很多前人留下的規則套用,像是SSO或是驗證登入等等
雖說play framework有提供自己的filter機制,但是畢竟很難在去自己再重新造輪子
所以必須使用前人的留下的servlet filter
幾經一番波折之後,在監聽封包的情況下確定POST DATA有送過來
那可能的問題就是出在servlet filter到play這段出了問題
一個簡單的示意圖如下(個人理解,不一定完全正確)
正常一個http request到了tomcat之後會變成HttpServletRequest並且自帶一個InputStream丟給servlet container如spring之類的
而play必須透過play2war這一層的包裝,除了一些基本的header資料之外剩下POST等透過InputStream讀取
但是一旦加了servlet filter的話,如下圖所示
如果filter有用到InputStream的話,如呼叫一些getParameterNames等函式
InputStream的資料就會變成HttpServletRequest的一部分,對servlet container沒有影響
但是play還在等待InputStream的資料被前面的filter吞掉了只剩下一個什麼都沒有的empty stream
因為這層關係讓play難以跟tomcat一般的filter共存
一個可行的方法是在一般filter之前加上一個wrapper filter對InputStream的資料進行cache
servlet filter在web.xml的設定是有順序的
透過warpper filter(圖中黃色部分)擋在最前面將資料cache起來除了供給其他filter使用,同時也不會影響到play對資料的讀取
有了MultiReadHttpServletRequest物件就可以自己簡單實作一個warpper filter
P.S. 上面的實作有bug,似乎會造成cookie或是其他filter的有意外狀況