REST:(Representational State Transfer)即表现层状态转换,定义了资源的通用访问格式,是一种网络应用程序的设计风格和开发方式。html
在概念中,须要理解如下几个名称:前端
即服务器上获取到的东西任何资源,一条用户记录,一个用户的密码,一张图片等等都是。node
即资源格式,是 HTML、XML、JSON、纯文本、图片等等,能够用各类各样的格式来表述你获取到的资源。git
即URL定位资源,用 HTTP 动词(GET,POST,DELETE,DETC)描述操做。操做是动词,资源是名词。github
即经过统一的接口对资源进行操做。spring
REST 一般基于使用 HTTP
, URI
,和 XML
以及 HTML
这些现有的普遍流行的协议和标准,每一种 URI 表明一种资源。express
REST 一般使用 JSON
数据格式。json
REST 基本架构的四个方法:api
下面会经过一个场景介绍。浏览器
REST 定义了资源的通用访问格式,接下来一个消费者为实例,介绍 RESTful API 定义:
GET /api/users
GET /api/users/100
POST /api/users
PUT /api/users/100
DELETE /api/users/100
GET /api/users/100/bill
GET /api/users/100/bill?from=201910&to=201911
以上其中 RESTful 风格 API 几乎包含常见业务状况。
本案例使用 mock 数据来演示,以下:
{ "user1" : { "name" : "leo", "password" : "123456", "profession" : "teacher", "id": 1 }, "user2" : { "name" : "pingan8787", "password" : "654321", "profession" : "librarian", "id": 2 }, "user3" : { "name" : "robin", "password" : "888888", "profession" : "clerk", "id": 3 } }
咱们将实现如下 RESTful API :
这一步咱们会建立 RESTful API 中的 /users,使用 GET 来读取用户的信息列表:
// index.js const express = require('express'); const app = express(); const fs = require("fs"); // 定义 读取用户的信息列表 的接口 app.get('/users', (req, res) => { fs.readFile( __dirname + "/" + "users.json", 'utf8', (err, data) => { console.log( data ); res.end( data ); }); }) const server = app.listen(8081, function () { const {address, port} = server.address(); console.log("server run in: http://%s:%s", address, port); })
这一步咱们会建立 RESTful API 中的 /users,使用 POST 来添加用户记录:
// index.js // 省略以前文件 只展现须要实现的接口 // mock 一条要新增的数据 const user = { "user4" : { "name" : "pingan", "password" : "password4", "profession" : "teacher", "id": 4 } } // 定义 添加用户记录 的接口 app.post('/users', (req, res) => { // 读取已存在的数据 fs.readFile( __dirname + "/" + "users.json", 'utf8', (err, data) => { data = JSON.parse( data ); data["user4"] = user["user4"]; console.log( data ); res.end( JSON.stringify(data)); }); })
这一步咱们在 RESTful API 中的 URI 后面加上 /users/:id,使用 GET 来获取指定用户详情:
// index.js // 省略以前文件 只展现须要实现的接口 // 定义 获取指定用户详情 的接口 app.get('/users/:id', (req, res) => { // 首先咱们读取已存在的用户 fs.readFile( __dirname + "/" + "users.json", 'utf8', (err, data) => { data = JSON.parse( data ); const user = data["user" + req.params.id] console.log( user ); res.end( JSON.stringify(user)); }); })
这一步咱们会建立 RESTful API 中的 /users,使用 DELETE 来删除指定用户:
// index.js // 省略以前文件 只展现须要实现的接口 // mock 一条要删除的用户id const id = 2; app.delete('/users', (req, res) => { fs.readFile( __dirname + "/" + "users.json", 'utf8', (err, data) => { data = JSON.parse( data ); delete data["user" + id]; console.log( data ); res.end( JSON.stringify(data)); }); })
客户端发出的数据操做指令都是"动词 + 宾语"的结构。
如上面提到的,GET /user
这个命令,GET
是动词,/user
是宾语。根据 HTTP 规范,动词一概大写。
动词一般有如下五种 HTTP 方法:
GET:读取(Read)
POST:新建(Create)
PUT:更新(Update)
PATCH:更新(Update),一般是部分更新
DELETE:删除(Delete)
宾语就是 API 的 URL,是 HTTP 动词做用的对象。它应该是名词,不能是动词。
好比,/users
是正确的,由于 URL 是名词,而下面就都是错误的了:
/getUsers /createUsers /deleteUsers
由于 URL 是名词,没有单复数的限制,可是仍是建议若是是一个集合,就使用复数形式。如 GET /users
来读取全部用户列表。
避免在多层级资源时,使用多级 URL。常见案例如获取某位用户的购买过的某一类商品:
GET /users/100/product/120
这种 URL 语意不明,也不利拓展,建议只有第一级,其余级别用查询字符串来表达:
GET /users/100?product=120
HTTP 五大类状态码有100多种,每一种状态码都有标准的(或者约定的)解释,客户端只需查看状态码,就能够判断出发生了什么状况,因此服务器应该返回尽量精确的状态码。
这边列举几个常用的状态码介绍:
API 返回的数据格式应该是 JSON 一个对象。
在发生错误时,若是还返回 200 状态码,前端须要解析返回数据才知道错误信息,这样实际上取消了状态码,是不恰当的。
正确的作法应该是在错误时,返回对应错误状态码,并将错误信息返回:
HTTP/1.1 400 Bad Request Content-Type: application/json { "error": "Invalid payoad.", "detail": { "surname": "This field is required." } }
本文首发在 pingan8787我的博客,如需转载请联系本人。
Author | 王平安 |
---|---|
pingan8787@qq.com | |
博 客 | www.pingan8787.com |
微 信 | pingan8787 |
每日文章推荐 | https://github.com/pingan8787... |
ES小册 | js.pingan8787.com |