要說RESTful首先來說說REST – REpresentational State Transfer (表述性狀態(tài)傳遞)
表述性狀態(tài)轉(zhuǎn)移是一組架構(gòu)約束條件和原則垫桂。滿足這些約束條件和原則的應(yīng)用程序或設(shè)計(jì)就是RESTful幌陕。需要注意的是盾鳞,REST是設(shè)計(jì)風(fēng)格而不是標(biāo)準(zhǔn)安皱。
以上的概念大概是許多關(guān)于RESTful中都會出現(xiàn)的定義概念刷袍。
那么什么是表述性狀態(tài)轉(zhuǎn)移呢米碰?
首先谷丸,之所以晦澀是因?yàn)榍懊嬷髡Z被去掉了堡掏,全稱是 Resource Representational State Transfer,通俗來講就是刨疼,資源在網(wǎng)絡(luò)中以某種表現(xiàn)形式進(jìn)行狀態(tài)轉(zhuǎn)移布疼。
在查詢很多資料后看到一句很精簡的總結(jié):
URL定位資源,用HTTP動詞(GET,POST,DELETE,PUT等)描述操作币狠。
既然說到了是用HTTP動詞進(jìn)行操作游两。那么需要了解這里列出的4.5個(gè)非常重要的HTTP動作,這里的0.5個(gè)是指PATCH漩绵,因?yàn)樗诠δ苌吓cPUT非常類似贱案,剩下4個(gè)通常被API開發(fā)人員兩兩結(jié)合使用
- GET(SELECT):從服務(wù)器獲取一個(gè)指定資源或一個(gè)資源集合;
- POST(CREATE):在服務(wù)器上創(chuàng)建一個(gè)資源止吐;
- PUT(UPDATE):更新服務(wù)器上的一個(gè)資源宝踪,需要提供整個(gè)資源;
- PATCH(UPDATE):更新服務(wù)器上的一個(gè)資源碍扔,只提供資源中改變的那部分屬性瘩燥;
- DELETE(DELETE):移除服務(wù)器上的一個(gè)資源;
還有兩個(gè)不常見的HTTP動作:
- HEAD – 獲取一個(gè)資源的元數(shù)據(jù)不同,例如一組hash數(shù)據(jù)或者資源的最近一次更新時(shí)間厉膀;
- OPTIONS – 獲取當(dāng)前用戶(Consumer)對資源的訪問權(quán)限;
關(guān)于RESTful的API設(shè)計(jì)風(fēng)格二拐,說完RESTful接下來該說說API了服鹅。
API是服務(wù)提供方和使用方之間的契約,打破該契約將會給服務(wù)端開發(fā)人員招來非常大的麻煩百新,這些麻煩來自于使用API的開發(fā)人員企软,因?yàn)閷PI的改動會導(dǎo)致他們的移動app無法工作。一個(gè)好的文檔對于解決這些事情能起到事半功倍的作用饭望,但是絕對多數(shù)程序員都不喜歡寫文檔仗哨。如果想讓服務(wù)端的價(jià)值更好的體現(xiàn)出來,就要好好設(shè)計(jì)API铅辞。通過這些API厌漂,你的服務(wù)/核心程序?qū)⒂锌赡艹蔀槠渌?xiàng)目所依賴的平臺;你提供的API越易用巷挥,就會有越多人愿意使用它桩卵。規(guī)劃API的展示形式可能比你想象的要簡單,首先要確定你的數(shù)據(jù)是如何設(shè)計(jì)以及核心程序是如何工作的。
image.png
也就是說Server提供的RESTful API中雏节,URL中只使用名詞來指定資源胜嗓,原則上不使用動詞」痴В“資源”是REST架構(gòu)或者說整個(gè)網(wǎng)絡(luò)處理的核心辞州。
那么下面來具體說說如何形成良好的RESTful風(fēng)格的API設(shè)計(jì)
1. 使用名詞而不是動詞
Server提供的RESTful API中,URL中只使用名詞來指定資源寥粹,原則上不使用動詞变过。“資源”是REST架構(gòu)或者說整個(gè)網(wǎng)絡(luò)處理的核心涝涤。比如:
http://api.qc.com/v1/newsfeed: 獲取某人的新鮮;
http://api.qc.com/v1/friends: 獲取某人關(guān)系列表;
-
http://api.qc.com/v1/profile: 獲取某人的詳細(xì)信息;
URL是對資源描述的抽象媚狰,資源的描述一定是名詞,如果引入了動詞阔拳,那這個(gè)URL就表示了一個(gè)動作崭孤,而非一個(gè)資源,這樣就偏離了REST的設(shè)計(jì)思想
2.Get方法和查詢參數(shù)不應(yīng)該涉及狀態(tài)改變
使用PUT, POST 和DELETE 方法 而不是 GET 方法來改變狀態(tài)糊肠,不要使用GET 進(jìn)行狀態(tài)改變:
通常辨宠,GET請求能夠被瀏覽器緩存(而且通常都會這么做),例如货裹,當(dāng)用戶發(fā)起第二次POST請求時(shí)嗤形,緩存的GET請求(依賴于緩存首部)能夠加快用戶的訪問速度。一個(gè)HEAD請求基本上就是一個(gè)沒有返回體的GET請求弧圆,因此也能被緩存赋兵。
3.使用復(fù)數(shù)名詞
不要混淆名詞單數(shù)和復(fù)數(shù),為了保持簡單墓阀,只對所有資源使用復(fù)數(shù)毡惜。
4. 使用子資源表達(dá)關(guān)系
如果一個(gè)資源與另外一個(gè)資源有關(guān)系,使用子資源:
5.使用Http頭聲明序列化格式
在客戶端和服務(wù)端斯撮,雙方都要知道通訊的格式,格式在HTTP-Header中指定
Content-Type 定義請求格式
Accept 定義系列可接受的響應(yīng)格式
6.使用HATEOAS
Hypermedia as the Engine of Application State 超媒體作為應(yīng)用狀態(tài)的引擎扶叉,超文本鏈接可以建立更好的文本瀏覽:
7.為集合提供過濾 排序 選擇和分頁等功能
Filtering過濾:
使用唯一的查詢參數(shù)進(jìn)行過濾:
GET /cars?color=red 返回紅色的cars
GET /cars?seats<=2 返回小于兩座位的cars集合
當(dāng)用戶請求獲取一組對象列表時(shí)勿锅,你就需要對結(jié)果進(jìn)行過濾并返回一組嚴(yán)格符合用戶要求的對象。有時(shí)返回結(jié)果的數(shù)量可能非常大枣氧,但是你也不能隨意對此進(jìn)行約束溢十,因?yàn)檫@種服務(wù)端的隨意約束會造成第三方開發(fā)人員的困惑。如果用戶請求了一個(gè)集合达吞,并對返回結(jié)果進(jìn)行遍歷张弛,然后只要前100個(gè)對象,那么這里就需要由用戶來指明這個(gè)限制量。這樣用戶就不會有這樣的疑惑:是他們程序的bug還是接口限制了100條吞鸭?還是網(wǎng)絡(luò)只允許傳這么大的包寺董?
Sorting排序:
允許針對多個(gè)字段排序
GET /cars?sort=-manufactorer,+model
這是返回根據(jù)生產(chǎn)者降序和模型升序排列的car集合
Field selection
移動端能夠顯示其中一些字段,它們其實(shí)不需要一個(gè)資源的所有字段刻剥,給API消費(fèi)者一個(gè)選擇字段的能力遮咖,這會降低網(wǎng)絡(luò)流量,提高API可用性造虏。
GET /cars?fields=manufacturer,model,id,color
Paging分頁
使用 limit 和offset.實(shí)現(xiàn)分頁御吞,缺省limit=20 和offset=0;
GET /cars?offset=10&limit=5
為了將總數(shù)發(fā)給客戶端漓藕,使用訂制的HTTP頭: X-Total-Count.
鏈接到下一頁或上一頁可以在HTTP頭的link規(guī)定陶珠,遵循Link規(guī)定:
Link:
https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5; rel=”next”,
https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3; rel=”last”,
https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5; rel=”first”,
https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5; rel=”prev”,
8.版本化你的API
也就是進(jìn)行版本控制。無論你在設(shè)計(jì)什么系統(tǒng)享钞,也不管你事先做了多么詳盡的計(jì)劃背率,隨著時(shí)間的推移和業(yè)務(wù)的發(fā)展,你的程序總會發(fā)生變化嫩与,數(shù)據(jù)關(guān)系也會發(fā)生變化寝姿,資源可能會被添加或者刪除一些屬性。只要軟件還在生存期內(nèi)并且還有人在用它划滋,開發(fā)人員就得面對這些問題饵筑,對于API設(shè)計(jì)來說,尤其如此处坪。
在URL中加入版本號是一個(gè)優(yōu)秀的API設(shè)計(jì)根资,當(dāng)然還有另一個(gè)常用的解決辦法就是把版本號放在請求首部中
使得API版本變得強(qiáng)制性,不要發(fā)布無版本的API同窘,使用簡單數(shù)字玄帕,避免小數(shù)點(diǎn)如2.5。一般在Url后面使用?v
/blog/api/v1
9. 使用Http狀態(tài)碼處理錯(cuò)誤
如果你的API沒有錯(cuò)誤處理是很難的想邦,只是返回500和出錯(cuò)堆棧不一定有用
Http狀態(tài)碼提供70個(gè)出錯(cuò)裤纹,我們只要使用10個(gè)左右:
200 – OK – 一切正常
201 – OK – 新的資源已經(jīng)成功創(chuàng)建
204 – OK – 資源已經(jīng)成功擅長
304 – Not Modified – 客戶端使用緩存數(shù)據(jù)
400 – Bad Request – 請求無效,需要附加細(xì)節(jié)解釋如 “JSON無效”
401 – Unauthorized – 請求需要用戶驗(yàn)證
403 – Forbidden – 服務(wù)器已經(jīng)理解了請求丧没,但是拒絕服務(wù)或這種請求的訪問是不允許的鹰椒。
404 – Not found – 沒有發(fā)現(xiàn)該資源
422 – Unprocessable Entity – 只有服務(wù)器不能處理實(shí)體時(shí)使用,比如圖像不能被格式化呕童,或者重要字段丟失漆际。
500 – Internal Server Error – API開發(fā)者應(yīng)該避免這種錯(cuò)誤。
1XX的返回碼預(yù)留給HTTP的底層使用夺饲,在你的整個(gè)職業(yè)生涯中都不會主動發(fā)送這種返回碼奸汇;
2XX的返回碼表示請求按照預(yù)期執(zhí)行并成功返回了信息施符。服務(wù)端要盡可能給用戶返回這種結(jié)果。
3XX的返回碼表示請求重定向擂找,大多數(shù)API都不會經(jīng)常使用這種請求()戳吝,但是最新的超媒體API會充分使用這些功能。
4XX的返回碼主要表示由客戶端引起的錯(cuò)誤婴洼,例如請求參數(shù)錯(cuò)誤或者訪問一個(gè)不存在的資源骨坑,這些必須為冪等操作,并且不能改變服務(wù)器的狀態(tài)(其實(shí)服務(wù)器的狀態(tài)發(fā)生了改變就意味著操作不是冪等了)柬采。
5XX的返回碼主要表示由服務(wù)器引起的錯(cuò)誤欢唾,通常情況下,這些錯(cuò)誤都是開發(fā)人員
使用詳細(xì)的錯(cuò)誤包裝錯(cuò)誤:
{
"errors": [
{
"userMessage": "Sorry, the requested resource does not exist",
"internalMessage": "No car found in the database",
"code": 34,
"more info": "http://dev.mwaysolutions.com/blog/api/v1/errors/12345"
}
]
}12345678910111213141516171819
10.允許覆蓋http方法
一些代理只支持POST 和 GET方法粉捻, 為了使用這些有限方法支持RESTful API礁遣,需要一種辦法覆蓋http原來的方法。
使用訂制的HTTP頭 X-HTTP-Method-Override 來覆蓋POST 方法.
使用場景
版本號
在 RESTful API 中肩刃,API 接口應(yīng)該盡量兼容之前的版本祟霍。但是,在實(shí)際業(yè)務(wù)開發(fā)場景中盈包,可能隨著業(yè)務(wù)需求的不斷迭代沸呐,現(xiàn)有的 API 接口無法支持舊版本的適配,此時(shí)如果強(qiáng)制升級服務(wù)端的 API 接口將導(dǎo)致客戶端舊有功能出現(xiàn)故障呢燥。實(shí)際上崭添,Web 端是部署在服務(wù)器,因此它可以很容易為了適配服務(wù)端的新的 API 接口進(jìn)行版本升級叛氨,然而像 Android 端、IOS 端仁连、PC 端等其他客戶端是運(yùn)行在用戶的機(jī)器上怖糊,因此當(dāng)前產(chǎn)品很難做到適配新的服務(wù)端的 API 接口遣钳,從而出現(xiàn)功能故障姐直,這種情況下姻成,用戶必須升級產(chǎn)品到最新的版本才能正常使用。
為了解決這個(gè)版本不兼容問題,在設(shè)計(jì) RESTful API 的一種實(shí)用的做法是使用版本號。一般情況下哨查,我們會在 url 中保留版本號浙于,并同時(shí)兼容多個(gè)版本。
【GET】 /v1/users/{user_id} // 版本 v1 的查詢用戶列表的 API 接口
【GET】 /v2/users/{user_id} // 版本 v2 的查詢用戶列表的 API 接口
現(xiàn)在,我們可以不改變版本 v1 的查詢用戶列表的 API 接口的情況下,新增版本 v2 的查詢用戶列表的 API 接口以滿足新的業(yè)務(wù)需求吆玖,此時(shí)翅阵,客戶端的產(chǎn)品的新功能將請求新的服務(wù)端的 API 接口地址漱贱。雖然服務(wù)端會同時(shí)兼容多個(gè)版本崇摄,但是同時(shí)維護(hù)太多版本對于服務(wù)端而言是個(gè)不小的負(fù)擔(dān)厕氨,因?yàn)榉?wù)端要維護(hù)多套代碼国葬。這種情況下,常見的做法不是維護(hù)所有的兼容版本汇四,而是只維護(hù)最新的幾個(gè)兼容版本接奈,例如維護(hù)最新的三個(gè)兼容版本序宦。在一段時(shí)間后糠惫,當(dāng)絕大多數(shù)用戶升級到較新的版本后备燃,廢棄一些使用量較少的服務(wù)端的老版本API 接口版本并齐,并要求使用產(chǎn)品的非常舊的版本的用戶強(qiáng)制升級漏麦。
注意的是,“不改變版本 v1 的查詢用戶列表的 API 接口”主要指的是對于客戶端的調(diào)用者而言它看起來是沒有改變测垛。而實(shí)際上捏膨,如果業(yè)務(wù)變化太大,服務(wù)端的開發(fā)人員需要對舊版本的 API 接口使用適配器模式將請求適配到新的API 接口上食侮。
資源路徑
RESTful API 的設(shè)計(jì)以資源為核心号涯,每一個(gè) URI 代表一種資源。因此锯七,URI 不能包含動詞链快,只能是名詞。注意的是起胰,形容詞也是可以使用的久又,但是盡量少用。一般來說效五,不論資源是單個(gè)還是多個(gè)地消,API 的名詞要以復(fù)數(shù)進(jìn)行命名。此外畏妖,命名名詞的時(shí)候脉执,要使用小寫、數(shù)字及下劃線來區(qū)分多個(gè)單詞戒劫。這樣的設(shè)計(jì)是為了與 json 對象及屬性的命名方案保持一致半夷。例如婆廊,一個(gè)查詢系統(tǒng)標(biāo)簽的接口可以進(jìn)行如下設(shè)計(jì)。
【GET】 /v1/tags/{tag_id}
同時(shí)巫橄,資源的路徑應(yīng)該從根到子依次如下淘邻。
/{resources}/{resource_id}/{sub_resources}/{sub_resource_id}/{sub_resource_property}
我們來看一個(gè)“添加用戶的角色”的設(shè)計(jì)奔坟,其中“用戶”是主資源读整,“角色”是子資源。
【POST】 /v1/users/{user_id}/roles/{role_id} // 添加用戶的角色
有的時(shí)候炊林,當(dāng)一個(gè)資源變化難以使用標(biāo)準(zhǔn)的 RESTful API 來命名彩倚,可以考慮使用一些特殊的 actions 命名筹我。
/{resources}/{resource_id}/actions/{action}
舉個(gè)例子,“密碼修改”這個(gè)接口的命名很難完全使用名詞來構(gòu)建路徑帆离,此時(shí)可以引入 action 命名蔬蕊。
【PUT】 /v1/users/{user_id}/password/actions/modify // 密碼修改
請求方式
可以通過 GET、 POST哥谷、 PUT岸夯、 PATCH、 DELETE 等方式對服務(wù)端的資源進(jìn)行操作呼巷。其中囱修,GET 用于查詢資源,POST 用于創(chuàng)建資源王悍,PUT 用于更新服務(wù)端的資源的全部信息破镰,PATCH 用于更新服務(wù)端的資源的部分信息,DELETE 用于刪除服務(wù)端的資源压储。
這里鲜漩,筆者使用“用戶”的案例進(jìn)行回顧通過 GET、 POST集惋、 PUT孕似、 PATCH、 DELETE 等方式對服務(wù)端的資源進(jìn)行操作刮刑。
【GET】 /users # 查詢用戶信息列表
【GET】 /users/1001 # 查看某個(gè)用戶信息
【POST】 /users # 新建用戶信息
【PUT】 /users/1001 # 更新用戶信息(全部字段)
【PATCH】 /users/1001 # 更新用戶信息(部分字段)
【DELETE】 /users/1001 # 刪除用戶信息
查詢參數(shù)
RESTful API 接口應(yīng)該提供參數(shù)喉祭,過濾返回結(jié)果。其中雷绢,offset 指定返回記錄的開始位置泛烙。一般情況下,它會結(jié)合 limit 來做分頁的查詢翘紊,這里 limit 指定返回記錄的數(shù)量蔽氨。
【GET】 /{version}/{resources}/{resource_id}?offset=0&limit=20
同時(shí),orderby 可以用來排序,但僅支持單個(gè)字符的排序鹉究,如果存在多個(gè)字段排序宇立,需要業(yè)務(wù)中擴(kuò)展其他參數(shù)進(jìn)行支持。
【GET】 /{version}/{resources}/{resource_id}?orderby={field} [asc|desc]
為了更好地選擇是否支持查詢總數(shù)自赔,我們可以使用 count 字段妈嘹,count 表示返回?cái)?shù)據(jù)是否包含總條數(shù),它的默認(rèn)值為 false匿级。
【GET】 /{version}/{resources}/{resource_id}?count=[true|false]
上面介紹的 offset蟋滴、 limit、 orderby 是一些公共參數(shù)痘绎。此外,業(yè)務(wù)場景中還存在許多個(gè)性化的參數(shù)肖粮。我們來看一個(gè)例子孤页。
【GET】 /v1/categorys/{category_id}/apps/{app_id}?enable=[1|0]&os_type={field}&device_ids={field,field,…}
注意的是,不要過度設(shè)計(jì)涩馆,只返回用戶需要的查詢參數(shù)行施。此外,需要考慮是否對查詢參數(shù)創(chuàng)建數(shù)據(jù)庫索引以提高查詢性能魂那。
狀態(tài)碼
使用適合的狀態(tài)碼很重要蛾号,而不應(yīng)該全部都返回狀態(tài)碼 200,或者隨便亂使用涯雅。這里鲜结,列舉筆者在實(shí)際開發(fā)過程中常用的一些狀態(tài)碼,以供參考活逆。
狀態(tài)碼 | 描述 |
---|---|
200 | 請求成功 |
201 | 創(chuàng)建成功 |
400 | 錯(cuò)誤的請求 |
401 | 未驗(yàn)證 |
403 | 被拒絕 |
404 | 無法找到 |
409 | 資源沖突 |
500 | 服務(wù)器內(nèi)部錯(cuò)誤 |
異常響應(yīng)
當(dāng) RESTful API 接口出現(xiàn)非 2xx 的 HTTP 錯(cuò)誤碼響應(yīng)時(shí)精刷,采用全局的異常結(jié)構(gòu)響應(yīng)信息。
HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"code": "INVALID_ARGUMENT",
"message": "{error message}",
"cause": "{cause message}",
"request_id": "01234567-89ab-cdef-0123-456789abcdef",
"host_id": "{server identity}",
"server_time": "2014-01-01T12:00:00Z"
}
請求參數(shù)
在設(shè)計(jì)服務(wù)端的 RESTful API 的時(shí)候蔗候,我們還需要對請求參數(shù)進(jìn)行限制說明怒允。例如一個(gè)支持批量查詢的接口,我們要考慮最大支持查詢的數(shù)量锈遥。
【GET】 /v1/users/batch?user_ids=1001,1002 // 批量查詢用戶信息
參數(shù)說明
- user_ids: 用戶ID串纫事,最多允許 20 個(gè)。
此外所灸,在設(shè)計(jì)新增或修改接口時(shí)丽惶,我們還需要在文檔中明確告訴調(diào)用者哪些參數(shù)是必填項(xiàng),哪些是選填項(xiàng)庆寺,以及它們的邊界值的限制蚊夫。
【POST】 /v1/users // 創(chuàng)建用戶信息
請求內(nèi)容
{
"username": "lgz", // 必填, 用戶名稱, max 10
"realname": "梁桂釗", // 必填, 用戶名稱, max 10
"password": "123456", // 必填, 用戶密碼, max 32
"email": "lianggzone@163.com", // 選填, 電子郵箱, max 32
"weixin": "LiangGzone", // 選填,微信賬號, max 32
"sex": 1 // 必填, 用戶性別[1-男 2-女 99-未知]
}
響應(yīng)參數(shù)
針對不同操作懦尝,服務(wù)端向用戶返回的結(jié)果應(yīng)該符合以下規(guī)范知纷。
【GET】 /{version}/{resources}/{resource_id} // 返回單個(gè)資源對象
【GET】 /{version}/{resources} // 返回資源對象的列表
【POST】 /{version}/{resources} // 返回新生成的資源對象
【PUT】 /{version}/{resources}/{resource_id} // 返回完整的資源對象
【PATCH】 /{version}/{resources}/{resource_id} // 返回完整的資源對象
【DELETE】 /{version}/{resources}/{resource_id} // 狀態(tài)碼 200壤圃,返回完整的資源對象。
// 狀態(tài)碼 204琅轧,返回一個(gè)空文檔
如果是單條數(shù)據(jù)伍绳,則返回一個(gè)對象的 JSON 字符串。
HTTP/1.1 200 OK
{
"id" : "01234567-89ab-cdef-0123-456789abcdef",
"name" : "example",
"created_time": 1496676420000,
"updated_time": 1496676420000,
...
}
如果是列表數(shù)據(jù)乍桂,則返回一個(gè)封裝的結(jié)構(gòu)體冲杀。
HTTP/1.1 200 OK
{
"count":100,
"items":[
{
"id" : "01234567-89ab-cdef-0123-456789abcdef",
"name" : "example",
"created_time": 1496676420000,
"updated_time": 1496676420000,
...
},
...
]
}
一個(gè)完整的案例
最后,我們使用一個(gè)完整的案例將前面介紹的知識整合起來睹酌。這里权谁,使用“獲取用戶列表”的案例。
【GET】 /v1/users?[&keyword=xxx][&enable=1][&offset=0][&limit=20] 獲取用戶列表
功能說明:獲取用戶列表
請求方式:GET
參數(shù)說明
- keyword: 模糊查找的關(guān)鍵字憋沿。[選填]
- enable: 啟用狀態(tài)[1-啟用 2-禁用]旺芽。[選填]
- offset: 獲取位置偏移,從 0 開始辐啄。[選填]
- limit: 每次獲取返回的條數(shù)采章,缺省為 20 條,最大不超過 100壶辜。 [選填]
響應(yīng)內(nèi)容
HTTP/1.1 200 OK
{
"count":100,
"items":[
{
"id" : "01234567-89ab-cdef-0123-456789abcdef",
"name" : "example",
"created_time": 1496676420000,
"updated_time": 1496676420000,
...
},
...
]
}
失敗響應(yīng)
HTTP/1.1 403 UC/AUTH_DENIED
Content-Type: application/json
{
"code": "INVALID_ARGUMENT",
"message": "{error message}",
"cause": "{cause message}",
"request_id": "01234567-89ab-cdef-0123-456789abcdef",
"host_id": "{server identity}",
"server_time": "2014-01-01T12:00:00Z"
}
錯(cuò)誤代碼
- 403 UC/AUTH_DENIED 授權(quán)受限