thinkjs REST API的跨域設置

用thinkjs也有一小段時間了,和其它國產框架同樣,起初是處於觀望態度。固然我最早的選擇也不是thinkjs而是選的express,用到後面發現實現一個能讓本身用着比較順手的博客仍是一件蠻困難或者說是繁瑣的事情。遠沒有本身起初所想的那樣簡單,再次感嘆一切貴在堅持...前端

express雖然足夠簡潔,不過想要重頭開始實現一個相對完善的博客程序無疑是須要很大工做量的,想到立刻過時的虛擬機,thinkjs這樣更加全面和強大的mvc框架變成了我理想的選擇,其中的諸多特性(靈活的路由,方便的MVC,完善的數據校驗,面向將來的Es6/7支持,簡潔的數據庫CURD操做等等)足夠本身使用了。ajax

-- 。--~囉嗦了,回到正題,因爲後臺管理界面我選擇了先後端分離的模式,並且分紅了兩塊不一樣的構建項目(有點折騰,不過我的以爲兩個攪和在一塊兒做爲一個項目進行構建會更讓我頭大哈哈,畢竟如今前端也變得複雜,有本身一套獨立的構建工具流),天然也有了跨域的需求,好在官方文檔有提供相對完善的配置說明,我用瞭如下設置:數據庫

this.header("Access-Control-Allow-Origin", this.header("origin") || "*"); 

彷佛簡單的一句就解決了跨域問題,得益於標準這確實解決了咱們一些跨域場景需求。 上邊提到的CORS是一個W3C標準,全稱是"跨域資源共享"(Cross-origin resource sharing)express

進一步的需求(支持跨域cookie)

跨域的同時我又遇到了須要給客戶端cookie,CORS一樣能夠作到, 能夠像下面這樣:後端

this.header('Access-Control-Allow-Credentials',true); // 在服務端設置 

// 客戶端一樣設置,這裏以Jquery爲例(約定好規則 😅相似一個願打一個願挨)api

// 跨域設置cokkie $.ajax({  url: a_cross_domain_url,  xhrFields: {  withCredentials: true } }); 

還能夠跨域設置cookie的需求咱們也解決了。跨域

進進一步的需求(支持REST API)

當我覺得一切OK的時候,REST的DELETE和PUT請求卻唱起了反調,這是要給好處費嗎....由於用到了REST API,僅使用上邊的設置還不能實現DELETE及PUT的跨域請求,表示我心裏當時是崩潰的,折騰了兩天,總算找到了問題所在,起先找的Thinkjs官網文檔,有提供例子,不看還好,這一看完全掉坑裏了。瀏覽器

Thinkjs官網文檔

// 若是是在 REST API,那麼能夠放在 __call 方法裏判斷,如: export default class extends think.controller.base { __call(){ let method = this.http.method.toLowerCase(); if(method === "options"){ this.setCorsHeader(); this.end(); return; } this.setCorsHeader(); return super.__call(); } setCorsHeader(){ this.header("Access-Control-Allow-Origin", this.header("origin") || "*"); this.header("Access-Control-Allow-Headers", "x-requested-with"); this.header("Access-Control-Request-Method", "GET,POST,PUT,DELETE"); this.header("Access-Control-Allow-Credentials", "true"); } } 

爬出坑的設置

// 服務端代碼 async __before() { this.header("Access-Control-Allow-Origin", this.header("origin") || "*"); this.header("Access-Control-Allow-Headers", "x-requested-with"); this.header("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE"); this.header('Access-Control-Allow-Credentials',true); let method = this.http.method.toLowerCase(); if(method === "options"){ this.end(); return; } let isLogin = await this.session('userInfo'); if(!isLogin){ this.fail('AUTH_FAILED'); } } 

this.header("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");安全

就是這傢伙了,隱藏得比較深,不過本質不壞,就靠它幹活。服務器

回顧並梳理

REST請求能夠分紅兩種,一種是簡單請求,GET,POST及HEAD都算其中。另外一種就是非簡單請求,顧名思意它要複雜一些,按鈕w3c規範它會先發一次預請求(Preflighted requests),去詢問下服務器我能不能知足要求,知足的話會返回一系列CORS頭信息設置,返回請求後客戶端一樣會驗證,這兩傢伙表示彼此都不信任對方0。0,客戶端會受瀏覽器的同源策略影響,由於相對GET POST HEAD請求,PUT DELETE請求安全性要求會更高些,驗證更嚴格也是理所應當的。其中Orgin會自動被服務端獲取,客戶端能夠不用配置,默認包含在請求頭中發送,其它的設置基本都須要兩兩對應設置。

兼容性

現代瀏覽器均支持,IE10有完整實現,IE8 9須要經過 XDomainRequest 對象來實現CORS(¬_¬)。

圖示

簡單請求

簡單請求

cokkie設置

cokkie設置

非簡單請求(預請求+主請求)

非簡單請求

綜合

綜合

Tips:想要更詳細的瞭解能夠查看底下列出的參考文檔!不知覺中表示寫的太多了點....

參考文檔

HTTP訪問控制(CORS)

相關文章
相關標籤/搜索