假設有一簡單架構分為前後兩部分,其一是Angular構成的前端頁面站點,另一個則是通過ASP.NET Web API搭建的後端服務站點。兩個站點因為分別佈署,所有會有CORS(Cross-Origin Resource Sharing)的問題。
再假設後端已經對此做好相應配置,比如在web.config里加上了:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET, PUT, POST, DELETE, HEAD" />
<add name="Access-Control-Allow-Headers" value="Origin, X-Requested-With, Content-Type, Accept" />
</customHeaders>
</httpProtocol>
那麼當前端呼叫後端介面:
save(data: any) : Observable<any> {
return this.http.post(`${this.apiUrl}`, data)
}
後端對應介面內的邏輯理論上應該是能夠被正常執行的:
[HttpPost]
[Route("api/save")]
public HttpResponseMessage Save(SomeModel model)
{
//內部邏輯
}
但結果是出現了Message:"The requested resource does not support http method `OPTIONS`."
錯誤。
產生此問題的原因在於HttpClient的post方法預設是採用application/json的內容型別(Content-Type)。
而CORS規範中有兩種型別:
- Simple requests
- Preflighted requests
前者無需額外的處理,但對於內容型別的支援,僅限三種:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
對於除此以外的內容型別,比如application/json,CORS會以預檢請求方式(Preflighted requests)處理。
Preflighted requests要求必須首先使用OPTIONS方法發起一個預檢請求到伺服器,以獲知伺服器是否允許該實際請求。
而在上面的後端服務程式碼中並沒有準備相應的處理OPTIONS請求的介面,所以才會有這樣的錯誤。
對應修正方法很簡單,在同一介面方法上加上處理OPTIONS請求的邏輯:
[HttpOptions, HttpPost]
[Route("api/save")]
public HttpResponseMessage Save(SomeModel model)
{
if (Request.Method == HttpMethod.Options) return new HttpResponseMessage(HttpStatusCode.OK);
//內部邏輯
}
有關CORS的詳細描述,建議參考官方文件——Cross-Origin Resource Sharing (CORS)