一種新的跨域解決方案:CORS(跨域資源共享)。javascript
它是W3c的工做草案,定義了在跨域訪問資源時瀏覽器和服務器之間如何通訊。html
CORS背後的基本思想是使用 自定義的HTTP頭部容許瀏覽器和服務器相互瞭解對方,從而決定請求或響應成功與否。java
CORS須要瀏覽器和服務器同時支持。目前,全部主流瀏覽器都支持該功能,IE瀏覽器不能低於IE8(IE10提供了對規範的完整支持;但在IE八、IE9中,CORS機制是藉由XDomainRequest
對象完成的)。編程
整個CORS通訊過程,都是瀏覽器自動完成,不須要用戶參與。對於開發者來講,CORS通訊與同源的AJAX通訊沒有差異,代碼徹底同樣。瀏覽器一旦發現AJAX請求跨源,就會自動添加一些附加的頭信息,有時還會多出一次附加的請求,但用戶不會有感受。跨域
所以,實現CORS通訊的關鍵是服務器。只要服務器實現了CORS接口,就能夠跨域通訊。瀏覽器
服務器端對於CORS的支持,主要就是經過設置Access-Control-Allow-Origin
來進行的。服務器
CORS能夠分紅兩種:app
一個簡單的請求大體以下:編程語言
HTTP方法是下列之一函數
HTTP頭包含
Content-Type,但僅能是下列之一
任何不符合上述要求的,都可以看作 複雜請求。爲何要區分簡單請求和複雜請求,由於瀏覽器對這兩種請求的處理方式是有區別的。對於複雜請求,瀏覽器跟服務器之間會有一次「預請求」。
先挖個坑,暫且不解釋預請求是什麼。
先說簡單請求:
對於簡單請求,瀏覽器直接發出CORS請求。具體來講,就是在頭信息之中,增長一個Origin字段。
下面是一個例子,瀏覽器發現此次跨源AJAX請求是簡單請求,就自動在頭信息之中,添加一個Origin字段。
Accept: */* Accept-Encoding: gzip, deflate, br Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Connection: keep-alive Host: localhost:3000 Origin: http://localhost Referer: http://localhost/ User-Agent: Mozilla/5.0 (Macintosh; .......
上面的頭信息中,Origin字段用來講明,本次請求來自哪一個源(協議 + 域名 + 端口)。服務器根據這個值,決定是否贊成此次請求。
若是Origin指定的源,不在許可範圍內,服務器會返回一個正常的HTTP迴應。瀏覽器發現,這個迴應的頭信息沒有包含Access-Control-Allow-Origin字段(詳見下文),就知道出錯了,從而拋出一個錯誤,被XMLHttpRequest的onerror回調函數捕獲。注意,這種錯誤沒法經過狀態碼識別,由於HTTP迴應的狀態碼有多是200。
若是Origin指定的域名在許可範圍內,服務器返回的響應,會多出幾個頭信息字段。
Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true Access-Control-Expose-Headers: FooBar Content-Type: text/html; charset=utf-8
上面的頭信息之中,有三個與CORS請求相關的字段,都以Access-Control-開頭。
var http = require('http'); http.createServer(function (req, res) { res.setHeader('Access-Control-Allow-Origin', '*'); res.write('hello world ~~~'); res.end(); }).listen(3000);
什麼是「預請求」?
瀏覽器先詢問服務器,當前網頁所在的域名是否在服務器的許可名單之中,以及可使用哪些HTTP動詞和頭信息字段。只有獲得確定答覆,瀏覽器纔會發出正式的XMLHttpRequest請求,不然就報錯。
在衆多的跨域方案中,JSONP跟CORS在使用方式上比較接近。
CORS與JSONP相比,更爲先進、方便和可靠。