在Web開發中,http跨域是一個很常見的問題,特別是在使用JavaScript進行客戶端編程時更是如此。http跨域簡單來說就是瀏覽器不能直接向不同源(域名、協議、端口號)的服務器發送請求,這種限制稱為同源策略。
假設我們的網站是www.abc.com,而我們在網站中需要訪問另外一個域名為www.xyz.com的后端API,我們會發現瀏覽器無法請求到對應的API數據并得到一個錯誤提示
Access to XMLHttpRequest at 'http://www.xyz.com/api/getdata' from origin 'http://www.abc.com' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
這個錯誤提示的原因是瀏覽器的同源策略禁止我們的JavaScript通過ajax請求到不同源的服務器。
那么我們該如何在JavaScript代碼中跨域請求數據呢?下面介紹幾種解決方案。
JSONP
JSONP的全稱是JSON with Padding,它利用script標簽可以跨域訪問資源的特性進行跨域數據請求。
let script = document.createElement('script'); script.src = 'http://www.xyz.com/abc?callback=parseData'; document.body.appendChild(script); function parseData(data){ // 處理接收到的數據 }
通過注入一個script標簽重新加載數據來實現jsonp跨域請求,但是jsonp只能發送GET請求。
CORS
CORS是Cross-Origin Resource Sharing的縮寫,它是一種可以允許跨域請求的機制。
在服務器端,只需要在請求響應中添加一些HTTP頭信息即可允許前端跨域訪問。
Access-Control-Allow-Origin:表示允許哪些源請求; Access-Control-Allow-Methods: 表示允許請求的方法; Access-Control-Allow-Headers: 表示允許請求的自定義header; Access-Control-Max-Age:表示對請求的響應進行緩存的時間長度(以秒為單位)。
如果我們的API服務器允許跨域訪問,添加頭信息到響應中即可:
Access-Control-Allow-Origin: * // 表示允許所有域名進行跨域訪問 Access-Control-Allow-Methods: GET, POST, PUT, DELETE Access-Control-Allow-Headers: Content-Type, Authorization
window.postMessage
window.postMessage可以進行跨iframe和跨窗口的通信,但是它需要在對應的窗口或iframe中定義一個監聽函數。
假如我們的父窗口在頁面中包含一個子iframe,子iframe中的腳本就可以使用postMessage與父窗口進行通信。
// iframe.html頁面代碼 window.parent.postMessage("Hello, parent", "*"); // 父窗口 window.addEventListener("message", function(event){ if (event.source != window) return; if (event.data == "Hello, parent") parentFunction(); });
后臺代理模式
有時候某些API服務器不允許跨域訪問,那么我們可以通過后臺代理模式來實現:
在我們的Web服務器上,我們可以寫一個中間代理程序來接收前端發送的請求,并將其轉發給API服務器。
在這種模式下,我們的前端代碼不直接訪問API服務器,而是向我們的代理服務器發送請求,代理服務器將請求重定向到API服務器。API服務器將響應返回給代理服務器,代理服務器再將響應返回到前端頁面。
以上是幾種常見的跨域請求解決方案,但是需要注意的是,每種方案都有各自的優缺點,開發者需要根據項目需求和實際情況選擇。