应该使用 GET/POST 获取返回 200 的状态码的 API
Warning
本文发布于 2023/12/12,内容可能已过时。
似乎所有人都这么做
经常做爬虫的时候总会观察到这么一个现象,很多网站的 API 都会只会返回 200 的状态码,即使是请求失败了,也会返回 200 的状态码,然后在返回的数据中会有一个 code
字段,用来表示请求是否成功,比如:
正好也看到知乎的一个讨论:为什么那么多公司做前后端分离项目后端响应的 HTTP 状态一律 200?
感觉确实很对,从运维的角度来看,这样做确实会方便很多。例如 vercel 的 log 对于大于 400 的状态码都会标黄或是标红,但很多时候都是只业务层面的错误,而不是系统层面的错误,这样的话就会造成很多误解,而且也不方便排查问题
而对于开发来讲,有些 fetch 客户端对于大于 400 的状态码都会抛出异常,这样的话就需要在每个请求的地方都去捕获异常……
再就是,面对复杂的业务逻辑,HTTP 状态码的表达能力实在是不足。虽然也能塞业务 code 到 body 里,但还是有些麻烦 hhhh
当然,还有个月经问题是,GET/POST 比 RESTful API 会舒服、直观很多,把操作方法放在 url 而不是 Method
所以再见了,RESTful API😹
实现
先说后端,我们可以继承自 Error 的类 MyError,然后设定一系列的业务错误码,然后在业务层面抛出 MyError 的实例,然后在中间件中捕获这个错误,以 200 的状态码返回
这里还涉及到了一个思想,就是不再使用频繁地使用 try-catch 来捕获异常,而是只用 throw 掉它,再在全局的地方去捕获它,这样的话就可以减少很多重复的代码
Nuxt Server
以 Nuxt.js/Nitro 为例,它支持手动配置全局的异常处理函数:errorHandler。需要现在 nuxt.config.ts 中添加:
然后捕获函数:
其中,对于错误码的定义,可以这么写
得益于 as const
,这里的 ErrorCode 的类型全是字面量字符串,提供了很好的类型补全。这样就不用使用枚举来实现了,只需要输入特定的字符串即可完成类型检查
对于返回的类型,可以这么写
Nest.js
Nest.js 是支持自定义异常处理的,实现 ExceptionFilter 即可
然后在全局模块中添加:
Spring Boot
SB 可以捕获在 Controller 中抛出的异常,然后在全局的地方去处理它,这里需要用到 @ControllerAdvice
注解,然后在类中添加 @ExceptionHandler
注解
但是,对于在 controller 层之前抛出的错误,如 Filter 等,就需要在 Filter 中手动捕获,然后重定向到一个特定的 error url,然后在这个 url 中再抛出错误,这样才能被 @ControllerAdvice
捕获到
其中,包装的统一 api response 的函数:
而一系列的错误码可以通过一个枚举类来定义