Skip to content

Commit b35ed52

Browse files
committed
2019.11.26
1 parent 847aeed commit b35ed52

1 file changed

Lines changed: 123 additions & 21 deletions

File tree

Cute-FullStack/【全栈修炼】RESTful架构及实践修炼宝典.md

Lines changed: 123 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,46 +55,46 @@ REST 基本架构的四个方法:
5555

5656
REST 定义了资源的通用访问格式,接下来一个消费者为实例,介绍 RESTful API 定义:
5757

58-
1. 获取所有 user
58+
1. 获取所有 users
5959

6060
```
61-
GET /api/user
61+
GET /api/users
6262
```
6363

64-
2. 获取指定 id 的 user
64+
2. 获取指定 id 的 users
6565

6666
```
67-
GET /api/user/100
67+
GET /api/users/100
6868
```
6969

70-
3. 新建一条 user 记录
70+
3. 新建一条 users 记录
7171

7272
```
73-
POST /api/user
73+
POST /api/users
7474
```
7575

76-
4. 更新一条 user 记录
76+
4. 更新一条 users 记录
7777

7878
```
79-
PUT /api/user/100
79+
PUT /api/users/100
8080
```
8181

82-
5. 删除一条 user 记录
82+
5. 删除一条 users 记录
8383

8484
```
85-
DELETE /api/user/100
85+
DELETE /api/users/100
8686
```
8787

88-
6. 获取一个 user 的所有消费账单
88+
6. 获取一个 users 的所有消费账单
8989

9090
```
91-
GET /api/user/100/bill
91+
GET /api/users/100/bill
9292
```
9393

9494
7. 获取一个 user 指定时间的消费账单
9595

9696
```
97-
GET /api/user/100/bill?from=201910&to=201911
97+
GET /api/users/100/bill?from=201910&to=201911
9898
```
9999

100100
以上其中 RESTful 风格 API 几乎包含常见业务情况。
@@ -132,7 +132,7 @@ GET /api/user/100/bill?from=201910&to=201911
132132

133133
### 2. 获取用户列表
134134

135-
这一步我们会创建 RESTful API 中的 **user**,使用 GET 来**读取用户的信息列表**
135+
这一步我们会创建 RESTful API 中的 **/users**,使用 GET 来**读取用户的信息列表**
136136

137137
```js
138138
// index.js
@@ -141,7 +141,7 @@ const app = express();
141141
const fs = require("fs");
142142

143143
// 定义 读取用户的信息列表 的接口
144-
app.get('/user', (req, res) => {
144+
app.get('/users', (req, res) => {
145145
fs.readFile( __dirname + "/" + "users.json", 'utf8', (err, data) => {
146146
console.log( data );
147147
res.end( data );
@@ -156,7 +156,7 @@ const server = app.listen(8081, function () {
156156

157157
### 3. 添加用户
158158

159-
这一步我们会创建 RESTful API 中的 **user**,使用 POST 来**添加用户记录**
159+
这一步我们会创建 RESTful API 中的 **/users**,使用 POST 来**添加用户记录**
160160

161161
```js
162162
// index.js
@@ -173,7 +173,7 @@ const user = {
173173
}
174174

175175
// 定义 添加用户记录 的接口
176-
app.post('/user', (req, res) => {
176+
app.post('/users', (req, res) => {
177177
// 读取已存在的数据
178178
fs.readFile( __dirname + "/" + "users.json", 'utf8', (err, data) => {
179179
data = JSON.parse( data );
@@ -186,14 +186,14 @@ app.post('/user', (req, res) => {
186186

187187
### 4. 获取用户详情
188188

189-
这一步我们在 RESTful API 中的 URI 后面加上 **:id**,使用 GET 来**获取指定用户详情**
189+
这一步我们在 RESTful API 中的 URI 后面加上 **/users/:id**,使用 GET 来**获取指定用户详情**
190190

191191
```js
192192
// index.js
193193
// 省略之前文件 只展示需要实现的接口
194194

195195
// 定义 获取指定用户详情 的接口
196-
app.get('/:id', (req, res) => {
196+
app.get('/users/:id', (req, res) => {
197197
// 首先我们读取已存在的用户
198198
fs.readFile( __dirname + "/" + "users.json", 'utf8', (err, data) => {
199199
data = JSON.parse( data );
@@ -206,7 +206,7 @@ app.get('/:id', (req, res) => {
206206

207207
### 5. 删除指定用户
208208

209-
这一步我们会创建 RESTful API 中的 **user**,使用 DELETE 来**删除指定用户**
209+
这一步我们会创建 RESTful API 中的 **/users**,使用 DELETE 来**删除指定用户**
210210

211211
```js
212212
// index.js
@@ -215,7 +215,7 @@ app.get('/:id', (req, res) => {
215215
// mock 一条要删除的用户id
216216
const id = 2;
217217

218-
app.delete('/user', (req, res) => {
218+
app.delete('/users', (req, res) => {
219219
fs.readFile( __dirname + "/" + "users.json", 'utf8', (err, data) => {
220220
data = JSON.parse( data );
221221
delete data["user" + id];
@@ -225,12 +225,114 @@ app.delete('/user', (req, res) => {
225225
})
226226
```
227227

228+
## 四、REST 最佳实践
229+
230+
### 1. URL 设计
231+
232+
#### 1.1 "动词 + 宾语"的操作指令结构
233+
234+
客户端发出的数据操作指令都是"**动词 + 宾语**"的结构。
235+
236+
如上面提到的,`GET /user` 这个命令,`GET` 是动词,`/user` 是宾语。根据 HTTP 规范,动词一律大写。
237+
238+
动词通常有以下五种 HTTP 方法:
239+
240+
GET:读取(Read)
241+
POST:新建(Create)
242+
PUT:更新(Update)
243+
PATCH:更新(Update),通常是部分更新
244+
DELETE:删除(Delete)
245+
246+
#### 1.2 宾语必须是名词
247+
宾语就是 API 的 URL,是 HTTP 动词作用的对象。它应该是名词,不能是动词。
248+
249+
比如,`/users` 是正确的,因为 URL 是名词,而下面就都是错误的了:
250+
```
251+
/getUsers
252+
/createUsers
253+
/deleteUsers
254+
```
255+
256+
#### 1.3 建议复数 URL
257+
258+
因为 URL 是名词,没有单复数的限制,但是还是建议如果是一个集合,就使用复数形式。如 `GET /users` 来读取所有用户列表。
259+
260+
#### 1.4 避免多级 URL
261+
262+
避免在多层级资源时,使用多级 URL。常见案例如**获取某位用户的购买过的某一类商品**:
263+
264+
```
265+
GET /users/100/product/120
266+
```
267+
268+
这种 URL 语意不明,也不利拓展,建议只有第一级,其他级别用查询字符串来表达:
269+
270+
```
271+
GET /users/100?product=120
272+
```
273+
274+
### 2. 准确的状态码表示
275+
276+
HTTP 五大类状态码有100多种,每一种状态码都有标准的(或者约定的)解释,客户端只需查看状态码,就可以判断出发生了什么情况,所以服务器应该返回尽可能精确的状态码。
277+
278+
这边列举几个经常使用的状态码介绍:
279+
280+
* **303 See Other**:表示参考另一个 URL。
281+
282+
* **400 Bad Request**:服务器不理解客户端的请求,未做任何处理。
283+
284+
* **401 Unauthorized**:用户未提供身份验证凭据,或者没有通过身份验证。
285+
286+
* **403 Forbidden**:用户通过了身份验证,但是不具有访问资源所需的权限。
287+
288+
* **404 Not Found**:所请求的资源不存在,或不可用。
289+
290+
* **405 Method Not Allowed**:用户已经通过身份验证,但是所用的 HTTP 方法不在他的权限之内。
291+
292+
* **410 Gone**:所请求的资源已从这个地址转移,不再可用。
293+
294+
* **415 Unsupported Media Type**:客户端要求的返回格式不支持。比如,API 只能返回 JSON 格式,但是客户端要求返回 XML 格式。
295+
296+
* **422 Unprocessable Entity**:客户端上传的附件无法处理,导致请求失败。
297+
298+
* **429 Too Many Requests**:客户端的请求次数超过限额。
299+
300+
* **500 Internal Server Error**:客户端请求有效,服务器处理时发生了意外。
301+
302+
* **503 Service Unavailable**:服务器无法处理请求,一般用于网站维护状态。
303+
304+
### 3. 服务端响应
305+
306+
#### 3.1 应该返回 JSON 对象
228307

308+
API 返回的数据格式应该是 JSON 一个对象。
309+
310+
#### 3.2 发生错误时,不要返回 200 状态码
311+
312+
在发生错误时,如果还返回 200 状态码,前端需要解析返回数据才知道错误信息,这样实际上取消了状态码,是不恰当的。
313+
314+
正确的做法应该是在错误时,返回对应错误状态码,并将错误信息返回:
315+
316+
```
317+
HTTP/1.1 400 Bad Request
318+
Content-Type: application/json
319+
320+
{
321+
"error": "Invalid payoad.",
322+
"detail": {
323+
"surname": "This field is required."
324+
}
325+
}
326+
```
327+
328+
329+
229330
## 参考资料
230331

231332
1. [《维基百科 - 表现层状态转换》](https://zh.wikipedia.org/wiki/%E8%A1%A8%E7%8E%B0%E5%B1%82%E7%8A%B6%E6%80%81%E8%BD%AC%E6%8D%A2)
232333
2. [《RESTful风格的springMVC》](https://blog.csdn.net/wy5612087/article/details/52149249)
233334
3. [《Node.js RESTful API》](https://www.runoob.com/nodejs/nodejs-restful-api.html)
335+
4. [《RESTful API 最佳实践》](www.ruanyifeng.com/blog/2018/10/restful-api-best-practices.html)
234336

235337
## 关于我
236338

0 commit comments

Comments
 (0)