Re: [討論] API沒資料,回200還是404比較好

軟工

46352

: 推 rollr: 回404的可以 fired 了 06/22 19:54
: → moom50302: 回404來亂的嗎? 06/22 20:45

嗯,我想兩位的建議可以寄信向 GitHub 和
Atlassian 這兩間公司說明一下,或許可以
幫他們團隊縮減人力。

當查詢資源不存在時返回 HTTP Code 404:

https://i.imgur.com/67gl9w8.png

https://i.imgur.com/Mysgpr4.png


[REF]
https://docs.github.com/en/rest

[REF]
https://docs.atlassian.com/ConfluenceServer/rest/7.18.1/#-getNodeById


---

在往下展開之前,我必須說下面的內容是以
RESTful API 設計風格的角度去看待,實現
上還有其他的方式可以採用。

REST = Representational State Transfer

‧網路上的資源,透過 URI 與之對應

‧資源可以有不同的表現形式,透過請求時
攜帶的 Content-Type/Accept 指定

‧透過 HTTP 協議方法轉化資源狀態

在 RESTful 架構中,每一個 URI 對應一種
資源,所以設計上會避免路徑出現動詞(動
詞用以轉化資源狀態,以 HTTP 協議的方法
來對應),而以名詞呈現;加上資料庫中存
放資料通常為資料的集合,因此多採用複數
形式(多個用戶/多篇文章/多個倉庫…)

---

以 GitHub REST API (v3) 的設計來回應推
文中提到的幾個問題,舉例來說:

[GET] /users
獲取使用者清單

[GET] /users/<USERNAME>
獲取指定使用者資訊

‧如果 USERNAME 不存在,返回 404

[GET] /users/<USERNAME>/followers
獲取指定使用者的追蹤者

‧如果 USERNAME 下沒有追蹤者
返回 200 與空陣列

---

差異在於以 REST 設計時,倘若今天你要拿
到 USERNAME 去進行請求,會假定你已經知
道要拿這個使用者下面的資料了,如果是使
用者不存在,代表是 Client 的問題,企圖
存取沒有的資源,當然是 404。

而訪問指定 USERNAME 下面的追蹤者時,是
要獲取資源清單,所以這時的空陣列就是他
的清單,只是空無一人,並不是沒有清單,
自然是 200 表示請求成功。

至於有人問說返回 404 怎麼跟 API 不存在
作區別,其實從上述的範例看的出來,今天
的 <USERNAME> 相當於是查詢用的參數,訪
問這個資源的確不存在,查詢資源的 API的
確不存在,兩件事情都成立呀!

因為此時 REST 設計要告訴你的就是「路徑
不存在,路徑又對應資源,資源不存在」

---

另外提一下推文有的一些謬誤:

‧HTTP Status Code 中的 4xx 代表客戶端
錯誤,而 5xx 才是伺服器錯誤,所以系
統錯誤更不該返回 404…

‧在 REST 中用 GET 拿資料,而 204 其實
代表的是「請求成功,但沒有 BODY」,
這個比較常用在 DELETE 操作…

---

順帶提一下,規範跟設計上是需要做取捨的
,比如 GitHub 其中有一段關於授權認證的
敘述:

「Requests that require authentication
will return 404 Not Found, instead of
403 Forbidden, in some places. This is
to prevent the accidental leakage of
private repositories to unauthorized
users.」

當沒有授權的使用者去獲取倉庫清單時,即
使是沒有權限,也必須先考慮到隱私性所以
返回 404 而不是 403 避免私有倉庫被沒有
權限的人知道:

> 沒有權限,但訪問 A 倉庫拿到 403
> 可以猜出有個私有倉庫 A
> 但使用者其實不想讓人知道他有這個倉庫

--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 111.82.214.46 (臺灣) ※ 文章網址: https://www.ptt.cc/bbs/Soft_Job/M.1655905888.A.728.html
Soarwind1樓推~ 很清楚, RESTful 是這樣 06/22 22:25
CMJ01212樓 06/22 22:35
cip6043樓 06/22 22:59
yehzu4樓推!認同此篇概念 06/22 23:03
lovdkkkk5樓推 不過最後的 403 404 好像反了 06/22 23:05
devilkool6樓 06/22 23:22
justaID7樓樓上,404 403 的例子應該沒有講反?先驗權限回403,缺 06/22 23:24
justaID8樓乏權限的連資源是否存在都不該讓 hacker 直到很合理 06/22 23:24
抱歉,這裡的確是我剛剛數字寫反了…我修 改了一下並把你想要說的補充上去
justaID9樓*樓樓上 06/22 23:24
justaID10樓*知道 (自動選字QQ 06/22 23:25
justaID11樓推這篇對 REST 描述得滿清楚 06/22 23:26
viper970912樓 06/22 23:27
justaID13樓我剛剛沒有注意 GitHub 原文那段,原來 GitHub in some 06/22 23:47
justaID14樓places 沒權限時回404,我個人本來以為應該優先回 403 06/22 23:47
justaID15樓比較合理 (無論背後資源是否存在,都回 403 並不會讓 u 06/22 23:47
justaID16樓nauthorized user 知道資源到底在不在),推測也許考量 06/22 23:47
justaID17樓觀點是:看到 403,hacker 會覺得背後資源有可能存在, 06/22 23:47
justaID18樓而繼續找其他方法突破 auth;但看到 404 很大機率是資源 06/22 23:47
justaID19樓真的不存在,effort 取捨下會放棄 hack 這個資源,避免 06/22 23:47
justaID20樓hack 半天一場空 06/22 23:47
無論「資源是否存在都回 403」 這件事情卡到的是有公開倉庫: 存在的公開倉庫有權限 200 存在的公開倉庫沒權限 200 存在的私有倉庫有權限 200 存在的私有倉庫沒權限 403 -> 被猜出 不存在的公開倉庫 404 -> 合理 不存在的公開倉庫 403 -> 不合理
Y7821樓 06/22 23:57
justaID22樓謝謝原po的列舉解說,以 Github 的 case 來說確實卡到了 06/23 00:44
justaID23樓公開倉庫 和私有倉庫 是同樣的 path pattern,無法在判 06/23 00:44
justaID24樓斷倉庫是否存在前就先以 403 阻擋 06/23 00:44
genius94525樓說得很清楚,推 06/23 01:10
Romulus26樓GitHub不要說REST了,就連網頁介面照樣丟404 XD 06/23 01:23
YYYero27樓 06/23 01:43
LeoSW28樓推這篇,寫得很清楚 06/23 08:15
DrTech29樓原文搞錯了。重點不在查詢資源存在不存在。而是你認為Clie 06/23 08:34
DrTech30樓nt的Request行為,是正常還是預期外的error。4xx開頭是 er 06/23 08:34