Appearance
cURL 用途很多,若想快速做個簡單的 API 請求測試,curl
是一個方便的指令,通常會使用 -X POST
來表明 POST 請求,然後搭配 -d '{ "key": "value" }'
傳送資料,如下:
sh
curl -X POST -d '{ "key": "value" }' https://example.com/api
在大部分的情境下,這個方法都能正常運作沒有問題,直到我遇到了一種會回應 302 Found
重新導向的 API,這個方法出現問題了!
也就是說這種 API 不會直接在 response body 回應你內容,而是藉由 HTTP status code 302 來告訴你「去另一個地方取得回應的內容」。
如果是用 Postman 這類的工具就不用擔心,它會自動幫你處理請求重定向的問題,Automatically follow redirects
設定預設是啟用的 ;而 curl 指令則是需要主動加上 -L
或 --location
來告訴 cURL 跟隨重定向取得結果,也就是:
sh
curl -L -X POST -d '{ "key": "value" }' https://example.com/api
但如果只是加入 -L
選項讓 curl 跟隨重定向,我依然得到了一個非預期的 405 Method Not Allowed
回應結果,沒理由同樣的 API 在 Postman 測試能正常運作,但在 curl 卻得到異常的回應。
最後在某個 stackoverflow comment 當中才知道一個冷知識,如果 curl 指令當中有 -d
或 --data
,請求會自動推導成 POST
,也就是說 -X POST
在這種情況下是多餘的,因為 -d
本身就會使請求變成 POST。
然而在這個案例中 -X POST
遇到了 302 重新定向不僅是多餘的問題,還會造成錯誤的結果,因為 -X POST
不僅會對第一個主要請求使用 POST,連 -L
產生的第二個請求也會使用 POST,所以才導致了我會收到 405 Method Not Allowed
的回應。
sh
# 正確取得 API 回應的流程:
# POST API -> 得到 302 Found 回應 -> GET data from new location -> 得到預期的結果
# 以下指令所產生的流程為:
# POST API -> 得到 302 Found 回應
curl -X POST -d '{ "key": "value" }' https://example.com/api
# 以下指令所產生的流程為:
# POST API -> 得到 302 Found 回應 -> POST data to new location -> 得到非預期的錯誤
curl -L -X POST -d '{ "key": "value" }' https://example.com/api
# 以下指令所產生的流程為:
# POST API -> 得到 302 Found 回應 -> GET data from new location -> 得到預期的結果
curl -L -d '{ "key": "value" }' https://example.com/api
API 回應 302 重新導向並不常見,我也只在 Google AppScript 所開發的 API 請求中遇到了這個問題。 總結來說,如果打算 POST 一個請求,且請求本身有使用到 -d
或 --data
,就不要再加上 -X POST
省得多做多錯。