Re: [討論] API沒資料,回200還是404比較好
: 推 rollr: 回404的可以 fired 了 06/22 19:54
: → moom50302: 回404來亂的嗎? 06/22 20:45
嗯,我想兩位的建議可以寄信向 GitHub 和
Atlassian 這兩間公司說明一下,或許可以
幫他們團隊縮減人力。
當查詢資源不存在時返回 HTTP Code 404:
https://i.imgur.com/67gl9w8.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
推
06/22 22:25,
1年前
, 1F
06/22 22:25, 1F
推
06/22 22:35,
1年前
, 2F
06/22 22:35, 2F
推
06/22 22:59,
1年前
, 3F
06/22 22:59, 3F
推
06/22 23:03,
1年前
, 4F
06/22 23:03, 4F
推
06/22 23:05,
1年前
, 5F
06/22 23:05, 5F
推
06/22 23:22,
1年前
, 6F
06/22 23:22, 6F
推
06/22 23:24,
1年前
, 7F
06/22 23:24, 7F
→
06/22 23:24,
1年前
, 8F
06/22 23:24, 8F
抱歉,這裡的確是我剛剛數字寫反了…我修
改了一下並把你想要說的補充上去
→
06/22 23:24,
1年前
, 9F
06/22 23:24, 9F
→
06/22 23:25,
1年前
, 10F
06/22 23:25, 10F
→
06/22 23:26,
1年前
, 11F
06/22 23:26, 11F
推
06/22 23:27,
1年前
, 12F
06/22 23:27, 12F
推
06/22 23:47,
1年前
, 13F
06/22 23:47, 13F
→
06/22 23:47,
1年前
, 14F
06/22 23:47, 14F
→
06/22 23:47,
1年前
, 15F
06/22 23:47, 15F
→
06/22 23:47,
1年前
, 16F
06/22 23:47, 16F
→
06/22 23:47,
1年前
, 17F
06/22 23:47, 17F
→
06/22 23:47,
1年前
, 18F
06/22 23:47, 18F
→
06/22 23:47,
1年前
, 19F
06/22 23:47, 19F
→
06/22 23:47,
1年前
, 20F
06/22 23:47, 20F
無論「資源是否存在都回 403」
這件事情卡到的是有公開倉庫:
存在的公開倉庫有權限 200
存在的公開倉庫沒權限 200
存在的私有倉庫有權限 200
存在的私有倉庫沒權限 403 -> 被猜出
不存在的公開倉庫 404 -> 合理
不存在的公開倉庫 403 -> 不合理
推
06/22 23:57,
1年前
, 21F
06/22 23:57, 21F
推
06/23 00:44,
1年前
, 22F
06/23 00:44, 22F
→
06/23 00:44,
1年前
, 23F
06/23 00:44, 23F
→
06/23 00:44,
1年前
, 24F
06/23 00:44, 24F
推
06/23 01:10,
1年前
, 25F
06/23 01:10, 25F
推
06/23 01:23,
1年前
, 26F
06/23 01:23, 26F
推
06/23 01:43,
1年前
, 27F
06/23 01:43, 27F
推
06/23 08:15,
1年前
, 28F
06/23 08:15, 28F
噓
06/23 08:34,
1年前
, 29F
06/23 08:34, 29F
→
06/23 08:34,
1年前
, 30F
06/23 08:34, 30F
→
06/23 08:34,
1年前
, 31F
06/23 08:34, 31F
→
06/23 08:34,
1年前
, 32F
06/23 08:34, 32F
好了啦,你要扯國際規範我拿給你呀:
https://www.rfc-editor.org/rfc/rfc7231#section-6.3.1
https://www.rfc-editor.org/rfc/rfc7231#section-6.3.5
The 404 (Not Found) status code indicates
that the origin server did not find a
current representation for the target
resource or is not willing to disclose that
one exists.
符合上述我說的 GitHub 設計時的兩種狀況
:
1. 資源不存在
2. 存在但不想被洩漏
拜託你要酸要噓之前,更新一下自己的認知
和當前規範有沒有差異好嗎?自己動手翻一
下你說的 RFC2616 也寫了:
https://i.imgur.com/ngpNzDp.png
Obsoleted by: 7230, 7231, 7232, 7233,
7234, 7235
拿明朝的劍斬清朝的官?但其實不論是你說
的 RFC2616 還是 RFC7231/RFC9110 都也沒
說錯,與微軟還有 GitHub 設計的狀況都不
謀而合。是你誤解了規範的說法,並忽略我
前面說的「在 REST 設計風格角度」下去看
待事情。
---
你說的「重點不在查詢資源存在不存在。而
是妳認為 Client 的請求行為,是正常還是
預期外的錯誤」
是你沒搞清楚吧?對於今天 Client 請求一
個不存在的 /users/<USERNAME>來說,當這
個 <USERNAME> 不存在時,就是你所說的預
期外的錯誤。
因為在 REST 設計的視角上,這是訪問一個
不存在的資源,返回 404一點懸念都沒有,
他正是你說的預期外的錯誤,在這個設計風
格下面,要以「資源」和「操作」來考量。
(拜託再往上翻一下國際規範,就我有上
色那一部分)
---
在應用場景下,他預期的是你先透過:
/users 獲取 <USERNAME>
/users/<USERNAME>/followers 獲取 <USERNAME>
/posts/<POST_ID>/authors 獲取 <USERNAME>
...
先拿到 <USERNAME> 才去打 /users/<USERNAME>
---
這是 REST 設計風格的不友善之處,因為拆
分路徑和設計返回的內容,切分粒度太細跟
切分粒度太粗,要嘛是我一下就拿到一大包
資料,有很多不必要的資訊,要嘛是我要層
層打好幾個請求才能拿到需要的資訊:
‧前者塞太多東西,費流
‧後者跨多個請求,佔線
可以改用 GraphQL 設計 API。
也可以單純用 RPC 方式處理。
推
06/23 08:55,
1年前
, 33F
06/23 08:55, 33F
推
06/23 08:56,
1年前
, 34F
06/23 08:56, 34F
推
06/23 09:37,
1年前
, 35F
06/23 09:37, 35F
推
06/23 10:16,
1年前
, 36F
06/23 10:16, 36F
還有 29 則推文
→
06/23 17:18,
1年前
, 66F
06/23 17:18, 66F
→
06/23 17:18,
1年前
, 67F
06/23 17:18, 67F
推
06/23 19:17,
1年前
, 68F
06/23 19:17, 68F
推
06/23 19:55,
1年前
, 69F
06/23 19:55, 69F
推
06/23 20:57,
1年前
, 70F
06/23 20:57, 70F
噓
06/23 21:49,
1年前
, 71F
06/23 21:49, 71F
→
06/23 21:49,
1年前
, 72F
06/23 21:49, 72F
你是不是搞錯什麼了?你所說的國際標準考
慮到 REST 的使用,在 2014 年增修了內容
,然後你一直說他增添的內容不符合國際標
準,大叔你是在哈囉?
https://i.imgur.com/r3WxHVV.png
不要只是噓文啊,拿你的國際標準寫篇文反
駁一下呀。我先跟你說在 RFC 7231 的第二
章就引用 [REST] 添加了資源(resource)
和表現層(Representations)的敘述。
拿出點證據來嘛!當大家沒看過文件?「說
話科學點,是身為工程師最基本的吧?」我
記得這好像是你說的?
推
06/23 22:09,
1年前
, 73F
06/23 22:09, 73F
推
06/23 23:02,
1年前
, 74F
06/23 23:02, 74F
→
06/23 23:03,
1年前
, 75F
06/23 23:03, 75F
→
06/23 23:03,
1年前
, 76F
06/23 23:03, 76F
→
06/23 23:05,
1年前
, 77F
06/23 23:05, 77F
→
06/23 23:07,
1年前
, 78F
06/23 23:07, 78F
→
06/23 23:09,
1年前
, 79F
06/23 23:09, 79F
推
06/23 23:24,
1年前
, 80F
06/23 23:24, 80F
→
06/24 03:08,
1年前
, 81F
06/24 03:08, 81F
→
06/24 03:08,
1年前
, 82F
06/24 03:08, 82F
→
06/24 03:08,
1年前
, 83F
06/24 03:08, 83F
→
06/24 03:08,
1年前
, 84F
06/24 03:08, 84F
→
06/24 03:08,
1年前
, 85F
06/24 03:08, 85F
→
06/24 03:08,
1年前
, 86F
06/24 03:08, 86F
上面並不是拿 RFC 2616 來佐證設計,而是
拿修正後的 RFC 723X 來說明 REST 風格的
合理性。
在 RFC 2616 還可以看到 URL 和 URN 的描
述,在 RFC 723X 就幾乎回歸到更為抽象的
URI 上了,更加強調「資源」的抽象概念。
你所謂中間那層的 adapater 其實就是文件
中對於 representation 的描述,而這也是
REST 風格的一部分:
「一個 URI 對應一種資源」
不論今天這個資源是一張圖片、一段文字、
一個頁面,都對應成一個 URI來表示。你要
提供資料庫中的使用者資訊、文章資訊,當
然也是可以,轉化成一個資源並對應,而在
目前多會以方便解析的結構化 JSON/XML 格
式表示這個資源。
另外必須補充一下,現代的客戶端並不是只
有網頁瀏覽器,如果都以瀏覽器的角度去看
的話,就很容易會因為你說的這個差異混淆
…
→
06/24 03:57,
1年前
, 87F
06/24 03:57, 87F
→
06/24 03:59,
1年前
, 88F
06/24 03:59, 88F
→
06/24 04:00,
1年前
, 89F
06/24 04:00, 89F
→
06/24 04:03,
1年前
, 90F
06/24 04:03, 90F
→
06/24 04:07,
1年前
, 91F
06/24 04:07, 91F
→
06/24 04:12,
1年前
, 92F
06/24 04:12, 92F
→
06/24 04:14,
1年前
, 93F
06/24 04:14, 93F
→
06/24 04:18,
1年前
, 94F
06/24 04:18, 94F
※ 編輯: Hsins (111.82.214.46 臺灣), 06/24/2022 09:22:36
→
06/24 12:30,
1年前
, 95F
06/24 12:30, 95F
→
06/24 12:31,
1年前
, 96F
06/24 12:31, 96F
→
06/24 12:32,
1年前
, 97F
06/24 12:32, 97F
→
06/24 12:32,
1年前
, 98F
06/24 12:32, 98F
推
06/24 15:07,
1年前
, 99F
06/24 15:07, 99F
推
06/24 16:26,
1年前
, 100F
06/24 16:26, 100F
→
06/24 16:26,
1年前
, 101F
06/24 16:26, 101F
推
06/26 03:27,
1年前
, 102F
06/26 03:27, 102F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 3 之 7 篇):