Swoft中間件跨域問題

swoft2.0.x官方文檔介紹的跨域處理demo以下:
image
這中方式在正常請求下看似沒有問題,但若是
$handler->handle($request)
步驟發生了異常,好比Validator攔截到請求參數不合法,拋出了ValidatorException,那麼後續添加請求頭的操做就沒法獲得執行.php

那麼,可不能夠在執行handle方法前先經過
Context::get()->getResponse()
得到Response對象,而後先對Response對象進行header設置呢?
答案是:NO,由於HttpContext沒有提供response屬性的setter,想要輸出修改後的Response只能在框架提供的各個環節中return給調用者.nginx

再看swoft源碼Swoft\Http\Server\HttpDispatcher:
image
不難發現:跨域

1.`$requestHandler->handle($request)`這一步若是發生異常,那麼咱們天然也得不到對應的`$response`.
2.發生異常後,系統會經過`$errDispatcher = Swoft::getSingleton(HttpErrorDispatcher::class)`獲得錯誤處理的調度者,最後經過錯誤處理調度者返回一個Response

結合源碼,最終的解決思路有4個:服務器

1.在每一箇中間件執行$handler->handle($request)步驟時加上try/catch,捕獲執行中的異常,而後獲取Response,設置好跨域後,正常return.
2.利用swoft的HttpErrorDispatcher,在對應的異常處理類裏面設置跨域的請求頭(關於如何設置異常處理,請參見swoft官網文檔).
3.跳出在php中設置跨域請求header的思路,在好比nginx等代理服務器設置header.
4.修改源碼,在以下時機加入header設置,此處的$this->configResponse($response)方法爲自定義的header設置方法:

image

以上4中方法:框架

前2中方法須要在註冊的每個中間件或者錯誤處理回調類裏面添加header設置,比較繁瑣.最可能是加個Common類來統一處理,但其它類仍然須要繼承這個Common類.
第3種方式無需動php任何代碼,推薦生產環境使用.可是在本地開發時須要Nginx等服務做爲代理,略顯繁瑣.
第4種方式,好處是隻需動一處代碼,就能做用全局.壞處也很明顯:動的那一處是框架提供的源碼.建議測試環境使用.

總結:測試

測試環境第4種,生產環境第3種.
相關文章
相關標籤/搜索