一、前言 由於項目是前後端分離,API介面與Web前端 部署在不同站點當中,因此在前文當中 "WebApi Ajax 跨域請求解決方法(CORS實現)" 使用跨域處理方式處理而不用 的方式。 但是在一段時間後,發現一個很奇怪的問題,每次前端發起請求的時候,通過瀏覽器的開發者工具都能看到在 下同一個 ...
一、前言
由於項目是前後端分離,API介面與Web前端 部署在不同站點當中,因此在前文當中WebApi Ajax 跨域請求解決方法(CORS實現)使用跨域處理方式處理而不用Jsonp
的方式。
但是在一段時間後,發現一個很奇怪的問題,每次前端發起請求的時候,通過瀏覽器的開發者工具都能看到在Network
下同一個url
有兩條請求,第一條請求的Method
為OPTIONS
,第二條請求的Method
才是真正的Get
或者Post
,並且,第一條請求無數據返回,第二條請求才返回正常的數據。
二、原因
第一個OPTIONS
的請求是由WEB伺服器處理跨域訪問引發的。OPTIONS
是一種預檢請求
,瀏覽器在處理跨域訪問的請求時,如果判斷請求為複雜請求,則會先向伺服器發送一條預檢請求,根據伺服器返回的內容,瀏覽器判斷伺服器是否允許訪問該請求。如果WEB伺服器採用CORS
的方式支持跨域訪問,在處理複雜請求時這個預檢請求是不可避免的。
由於我們的WEB伺服器採用CORS
來解決跨域訪問的問題,同時在header
中添加了自定義參數以及使用json
格式來進行數據交互,導致我們的每次請求都是複雜請求,從而產生每次請求都會發送兩條請求的現象。
產生原因如下:
- 使用
CORS
解決跨域問題
三、解決方案
3.1 Nginx
3.1.1 思路
- 將前端項目部署在
Nginx
當中,通過代理的方式來解決跨域請求問題
3.1.2 實現
3.1.2.1 安裝 Nginx
Windows 下 安裝 Nginx 最簡單,直接下載壓縮包,然後解壓後
3.1.2.2 配置 Nginx
已自帶預設配置,如要部署Vue
、Angular
這種單頁面應用,將打包後的index.html
文件以及dist
目錄放到發佈目錄中,將路徑複製,用於配置Nginx
服務指向
配置文件如下:
server {
listen 9461; # 監聽埠號
server_name localhost 192.168.88.22; # 訪問地址
location / {
root 項目路徑; # 例如:E:/Publish/xxx/;
index index.html;
# 此處用於處理 Vue、Angular、React 使用H5 的 History時 重寫的問題
if (!-e $request_filename) {
rewrite ^(.*) /index.html last;
break;
}
}
# 代理服務端介面
location /api {
proxy_pass http://localhost:9460/api;# 代理介面地址
}
}
3.1.2.3 Nginx 常用命令
- 啟動:start nginx
- 重新載入配置:nginx -s reload
- 重新打開日誌文件:nginx -s reopen
- 測試配置文件是否正確:nginx -t [可選:指定路徑]
- 快速停止:nginx -s stop
- 有序停止:nginx -s quit
3.1.3 Nginx 單頁面應用H5 History Url重寫
- 支持
Vue、Angular、React - 原因
實現單頁面時,刷新頁面會產生頁面找不到的問題,所以需要重寫Url地址到index.html當中。 - 註意點
在使用Nginx
中URL重寫的時候,一直報錯如下
檢查後,發現if
和(
之間必須有個空格。
3.2 Other
3.2.1 思路
- 既然要發送預檢請求,是否可以減少預檢請求的次數?
- 例如可以設定一個有效期,在有效期內不再重覆預檢。
3.2.2 實現
可以在服務端處預檢完成後加入一個Access-Control-Max-Age
請求頭來解決這個問題。
3.2.3 CORS 響應欄位說明
- Access-Control-Allow-Methods
該欄位必需,它的值是逗號分隔的一個字元串,表明伺服器支持的所有跨域請求的方法。
註意,返回的是所有支持的方法,而不單是瀏覽器請求的那個方法。這是為了避免多次"預檢"請求。 - Access-Control-Allow-Headers
如果瀏覽器請求包括Access-Control-Request-Headers
欄位,則Access-Control-Allow-Headers
欄位是必需的。
它也是一個逗號分隔的字元串,表明伺服器支持的所有頭信息欄位,不限於瀏覽器在"預檢"中請求的欄位。 - Access-Control-Allow-Credentials
該欄位與簡單請求時的含義相同。 - Access-Control-Max-Age
該欄位可選,用來指定本次預檢請求的有效期,單位為秒。上面結果中,有效期是20天(1728000秒),即允許緩存該條回應1728000秒(即20天),在此期間,不用發出另一條預檢請求。
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Allow-Credentials: true
Access-Control-Max-Age: 1728000