CORS和JSON的大坑

最近好像很常碰到 CORS 的問題,所以順手記錄一下,日後再次掉進坑才能快點爬出來。

TL;DR

如果有用到 JSON,請記得再加上 Access-Control-Allow-Headers 允許 application/json*

前情提要

有在開發網站而且前後端分離的人多多少少都會碰過 CORS 的問題,這個原先出發點是為了安全,但有時候真的很惱人。

最近同事踩到了這個坑,我們看來看去弄了半天,Access-Control-Allow-Origin 也設定成 * 了還是不行,但當 POST 不是用 application/json 而是其他的(例如:form-data 或是 x-www-form-urluncoded)就可以成功。原本想說那就這樣就解決了,可是是別人指定的就是要這種方式,只好繼續想辦法。

排錯

這邊跟大家推薦一個好東西──hoppscotch,可以把它當成開源的 Postman,不過受制於一些限制,有些地方還是可惜了點,不過通常開發很夠用了。

我就用了上方這套工具測試,這時發現了如圖的錯誤:

嗯……’Access-Control-Allow-Headers’ 不允許「Content-Type」?

上網往這個方向 google 一下,找到了一篇大神的文章,這邊直接引用其中一段:

只要不符合簡單請求的規則例如使用了 PUTDELETE 等 Method 或者 Content-Typeapplication/json,在送出該 Request 之前,瀏覽器會先進行一次預檢(Preflight),和簡單請求不同的是如果沒有通過預檢,就不會發送 Request。

抓到了!原來是 JSON 在搞鬼!話說這是為什麼針對 JSON 啊啊啊

解法

總之知道問題點,事情就好辦多了。那就是在回傳的 header 加上 Access-Control-Allow-Headers * 或是 Access-Control-Allow-Headers application/json 就可以了。

如果是 CloudFront 的話想偷懶可以用簡單的設定(是說受託管政策中都沒有針對 Access-Control-Allow-Headers 的真奇怪?只能自己設定一個了):

如果是 Nginx 的話則:

1
2
3
4
5
6
7
server{
# something
add_header Access-Control-Allow-Origin *;
# 除了上面這行,再增加下面這行
add_header Access-Control-Allow-Headers *;
# something
}

好了問題解決,收工!