日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Restful API 中的错误处理方案

發布時間:2023/12/10 编程问答 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Restful API 中的错误处理方案 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

簡介

隨著移動開發和前端開發的崛起,越來越多的 Web 后端應用都傾向于實現 Restful API。

Restful API 是一個簡單易用的前后端分離方案,它只需要對客戶端請求進行處理,然后返回結果即可, 無需考慮頁面渲染,一定程度上減輕了后端開發人員的負擔。

然而,正是由于 Restful API 不需要考慮頁面渲染,導致它不能在頁面上展示錯誤信息。

那就意著當出現錯誤的時候,它只能通過返回一個錯誤的響應,來告訴用戶和開發者相應的錯誤信息,提示他們接下來應該怎么辦。

本文將討論 Restful API 中的錯誤處理方案。

設計錯誤信息

當 Restful API 需要拋出錯誤的時候,我們要考慮的是:這個錯誤應該包含哪些信息。

Github (use http status)

{"message":?"Validation?Failed","errors":?[{"resource":?"Issue","field":?"title","code":?"missing_field"}] }

Google (use http status)

{"error":?{"errors":?[{"domain":?"global","reason":?"insufficientFilePermissions","message":?"The?user?does?not?have?sufficient?permissions?for?file?{fileId}."}],"code":?403,"message":?"The?user?does?not?have?sufficient?permissions?for?file?{fileId}."} }

Facebook (use http status)

{"error":?{"message":?"Message?describing?the?error",?"type":?"OAuthException","code":?190,"error_subcode":?460,"error_user_title":?"A?title","error_user_msg":?"A?message","fbtrace_id":?"EJplcsCHuLu"} }

Twitter (use http status)

{"errors":?[{"message":?"Sorry,?that?page?does?not?exist","code":?34}] }

Twilio (use http status)

{"code":?21211,"message":?"The?'To'?number?5551234567?is?not?a?valid?phone?number.","more_info":?"https://www.twilio.com/docs/errors/21211","status":?400 }

觀察這些結構可以發現它們都有一些共同的地方:

都利用了 Http 狀態碼

有些返回了業務錯誤碼

都提供了給用戶看的錯誤提示信息

有些提供了給開發者看的錯誤信息

Http 狀態碼

在 Restful API 中利用 Http 狀態碼來表明錯誤類型再合適不過了,因為 Http 狀態碼定義了很多抽象的錯誤類型。

雖然 Http 狀態碼定義了非常多的錯誤類型,但實際應用中,我們常用的狀態碼并不多,通常都是下面這幾方面:

API 正常工作 (200, 201)

客戶端錯誤 (400, 401, 403, 404)

服務端錯誤 (500, 503)

業務錯誤碼

很多時候,我們根據業務類型來自定義錯誤碼。

這些業務錯誤碼與 Http 狀態碼并不重疊,這時候我們可以返回業務錯誤碼,用來提示用戶/開發者錯誤類型。

給用戶看的錯誤信息

當出現錯誤的時候,我們需要提示用戶如何處理這種情況,通常這種錯誤信息都是必須的。

給開發者看的錯誤信息

若我們的 API 需要開放給第三方開發者,那么我們就需要考慮返回一些給開發者看的錯誤信息。

設計錯誤類型

我們剛才提到過,可以利用 Http 狀態碼來為錯誤類型進行分類。

通常我們所說的分類通常是對客戶端錯誤進行分類, 即 4xx 類型的錯誤。

而這些錯誤類型中,我們最常用的是:

400 Bad Request

由于包含語法錯誤,當前請求無法被服務器理解。除非進行修改,否則客戶端不應該重復提交這個請求。

通常在請求參數不合法或格式錯誤的時候可以返回這個狀態碼。

401 Unauthorized

當前請求需要用戶驗證。

通常在沒有登錄的狀態下訪問一些受保護的 API 時會用到這個狀態碼。

403 Forbidden

服務器已經理解請求,但是拒絕執行它。與401響應不同的是,身份驗證并不能提供任何幫助。

通常在沒有權限操作資源時(如修改/刪除一個不屬于該用戶的資源時)會用到這個狀態碼。

404 Not Found

請求失敗,請求所希望得到的資源未被在服務器上發現。

通常在找不到資源時返回這個狀態碼。

盡管我們可以通過 Http 狀態碼來表示錯誤的類型,但在實際應用中,如果僅僅使用 Http 狀態碼的話,我們的代碼中就遍布 Http 狀態碼:

//?Node.js if?(!res.body.title)?{res.statusCode?=?400 }if?(!user)?{res.statusCode?=?401 }if?(!post)?{res.statusCode?=?404 }

上面的實現方式在小項目中還可以接受,當項目變大、需求變多的時候,維護起來就變得很麻煩了。

我個人習慣把錯誤分成以下幾種類型:

格式錯誤 (FORMAT_INVALID)

數據不存在 (DATA_NOT_FOUND)

數據已存在 (DATA_EXISTED)

數據無效 (DATA_INVALID)

登錄錯誤 (LOGIN_REQUIRED)

權限不足 (PERMISSION_DENIED)

錯誤分類之后,我們拋錯誤的時候就變得更加直觀了:

if?(!res.body.title)?{throw?new?Error(ERROR.FORMAT_INVALID) }if?(!user)?{throw?new?Error(ERROR.LOGIN_REQUIRED) }if?(!post)?{throw?new?Error(ERROR.DATA_NOT_FOUND) }if?(post.creator.id?!==?user.id)?{throw?new?Error(ERROR.PERMISSION_DENIED) }

這種形式比上面的寫死狀態碼的方式方便很多,而且維護起來也更加簡單。

但有一個問題,就是不能根據錯誤類型來返回指定的錯誤信息。

自定義錯誤類型

要實現根據錯誤類型來返回指定的錯誤信息,我們可以通過自定義錯誤的方式來實現。

假設我們自定義錯誤的結構如下:

{"type":?"","code":?0,"message":?"","detail":?"" }

我們需要做到如下幾點:

1.根據錯誤類型來自動設置type, code, message

2.detail 為可選項,用來描述該錯誤的具體原因

const?ERROR?=?{FORMAT_INVALID:?'FORMAT_INVALID',DATA_NOT_FOUND:?'DATA_NOT_FOUND',DATA_EXISTED:?'DATA_EXISTED',DATA_INVALID:?'DATA_INVALID',LOGIN_REQUIRED:?'LOGIN_REQUIRED',PERMISSION_DENIED:?'PERMISSION_DENIED' }const?ERROR_MAP?=?{FORMAT_INVALID:?{code:?1,message:?'The?request?format?is?invalid'},DATA_NOT_FOUND:?{code:?2,message:?'The?data?is?not?found?in?database'},DATA_EXISTED:?{code:?3,message:?'The?data?has?exist?in?database'},DATA_INVALID:?{code:?4,message:?'The?data?is?invalid'},LOGIN_REQUIRED:?{code?5,message:?'Please?login?first'},PERMISSION_DENIED:?{code:?6,message:?'You?have?no?permission?to?operate'} }class?CError?extends?Error?{constructor(type,?detail)?{super()Error.captureStackTrace(this,?this.constructor)let?error?=?ERROR_MAP[type]if?(!error)?{error?=?{code:?999,message:?'Unknow?error?type'}}this.name?=?'CError'this.type?=?error.code?!==?999???type?:?'UNDEFINED'this.code?=?error.codethis.message?=?error.messagethis.detail?=?detail} }

自定義好錯誤之后,我們調用起來就更加簡單了:

//?in?controller if?(!user)?{throw?new?CError(ERROR.LOGIN_REQUIRED,?'You?should?login?first') }if?(!req.body.title)?{throw?new?CError(ERROR.FORMAT_INVALID,?'Title?is?required') }if?(!post)?{throw?new?CError(ERROR.DATA_NOT_FOUND,?'The?post?you?required?is?not?found') }

最后,還剩下一個問題,根據錯誤類型來設置狀態碼,然后返回錯誤信息給客戶端。

捕獲錯誤信息

在 Controller 中拋出自定義錯誤后,我們需要捕獲該錯誤,才能返回給客戶端。

假設我們使用 koa 2 作為 web 框架來開發 restful api,那么我們要做的是添加錯誤處理的中間件:

module.exports?=?async?function?errorHandler?(ctx,?next)?{try?{await?next()}?catch?(err)?{let?statusswitch?(err.type)?{case?ERROR.FORMAT_INVALID:case?ERROR.DATA_EXISTED:case?ERROR.DATA_INVALID:status?=?400breakcase?ERROR.LOGIN_REQUIRED:status?=?401case?ERROR.PERMISSION_DENIED:status?=?403case?ERROR.DATA_NOT_FOUND:status?=?404breakdefault:status?=?500}ctx.status?=?statusctx.body?=?err} }//?in?app.js app.use(errorHandler) app.use(router.routes())

通過這種方式,我們就能優雅地處理 Restful API 中的錯誤信息了。

總結

以上是生活随笔為你收集整理的Restful API 中的错误处理方案的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。