RESTful基础与基于资源的API实践
RESTful基础
RESTful是什么
RESTful是什么?
本质:一种软件架构风格
核心:面向资源
解决的问题:降低开发的复杂性,提高系统的可伸缩性
设计概念和准则:
- 网络上所有的事物都可以被抽象为资源
- 每个资源都有唯一的资源标识,对资源的操作不会改变这些标识
- 所有的操作都是无状态的
资源”就是网络上的一个实体,或者说网络上的一个具体信息。(比如文本、音频、视频等)
完整的URL地址
schema://host[:post]/path[?query-string][#anchor]
,说明:
- schema:指定底层使用的协议,例如:http,https,ftp
- host:服务器的IP地址或者域名
- port:服务器端口,默认为80
- path:访问资源的路径
- query-string:发送给http服务器的数据
- anchor:锚(定义页面特定章节位置)
请求的组成格式
请求行+消息报头+请求正文
- 请求行:
Method Request-URI HTTP-Version CRLF
例如:GET /HTTP/1.1 CRLF
(CRLF回车或换行符)- 请求方式(HTTP动词):
常用:- GET: 检索位于指定 URI 处的资源的表示形式
- POST:在指定的 URI 处创建新资源。 请求消息的正文将提供新资源的详细信息。 请注意,POST 还用于触发不实际创建资源的操作
- PUT:在指定的 URI 处创建或替换资源。 请求消息的正文指定要创建或更新的资源
- PATCH:对资源执行部分更新。 请求正文包含要应用到资源的一组更改
- DELETE:删除位于指定 URI 处的资源
不常用: - HEAD:请求获取由Request -URI所标识的资源的响应消息报头
- OPTIONS:请求查询服务器的性能,或者查询与资源相关的选项和需求
- 请求方式(HTTP动词):
响应组成格式
状态行+消息报头+响应正文
- 状态行:
HTTP-Version Status-Code Reason-Phrase CRLF
,例如HTTP/1.1 200 OK
- 典型状态码:参见RESTful HTTP 的实践
基于资源的API实践
模仿Github,设计一个博客网站的 API
Base URL
所有的API访问都是通过HTTPS进行的,可以从https://api.mydomain.com
访问。所有数据都作为JSON发送和接收。
用户注册博客账号
为了注册一个新的用户,需要向user
路径发送一个POST
请求,注册用户需提供用户名、密码和邮箱:
curl -X POST \
-d '{"username":"Wyb","password":"0805happy","email":"1997happy@163.com"}' \
https://api.mydomain.com/users
当创建成功时,HTTP返回为201 Created
,Location 头包含了新用户的URL,例如:
Status: 201 Created
Location: https://api.mydomain.com/users/55a47496e4b05001a7732c5f
返回的主体是一个 JSON 对象,包含 objectId,createdAt 时间戳表示创建对象时间:
{
"createdAt":"2015-07-14T02:31:50.100Z",
"objectId":"55a47496e4b05001a7732c5f"
}
用户登录博客账号
需要提供正确的用户名及密码才能够成功登录
curl -i https://api.mydomain.com -u valid_username:valid_password
因错误的用户名及密码登录失败,返回401 Unauthorized
curl -i https://api.mydomain.com -u wrong_username:wrong_password
HTTP/1.1 401 Unauthorized
{
"message": "Bad credentials",
"documentation_url": "https://developer.mydomain.com/v1"
}
如果短时间内连续多次使用错误的用户名及密码登录失败,API将暂时拒绝该用户的所有登录尝试(包括输入正确的用户名和密码的尝试),返回403 Forbidden
curl -i https://api.mydomain.com -u valid_username:valid_password
HTTP/1.1 403 Forbidden
{
"message": "Maximum number of login attempts exceeded. Please try again later.",
"documentation_url": "https://developer.mydomain.com/v1"
}
获取博客内容
通过发送一个GET请求到类的URL上,不需要任何URL参数,就可以一次获取多个对象。下面就是简单地获取所有公开发表的博客内容:
curl -X GET \
https://api.mydomain.com/classes/Post
返回的值就是一个 JSON 对象包含了 results 字段,它的值就是对象的列表,例如:
{
"results": [
{
"content": "这个超级酷,超级适合我的酷盖!!@UNIQ-王一博 //@UNIQ-王一博:电力满格,锋芒无限。我是奥迪Q2L e-tron全能体验官,快来和我一起感受Q2L e-tron的电动魅力!#想坐王一博的副驾驶#",
"pubUser": "Wang Yibo's Fan",
"createdAt": "2019-10-01 03:08:05",
"objectId": "55a39634e4b0ed48f0c1845b"
},
{
"content": "#王一博有翡# wyb #王一博谢允# 愿时光不负岁月, 愿世界不负温柔, 愿每一个善良的人都被认真对待, 千山万重, 不离不弃, 未来可期!@UNIQ-王一博",
"pubUser": "Wang Yibo's Fan",
"createdAt": "2019-11-01 01:08:05",
"updatedAt": "2019-11-11 02:08:05",
"objectId": "558e20cbe4b060308e3eb36c"
}
]
}
加入查询约束
通过where
参数的形式可以对查询对象做出约束。
- 查看指定用户发表的博客
假设指定用户为Wang Yibo
:curl -X GET \ -G \ --data-urlencode 'where={"pubUser":"Wang Yibo"}' \ https://api.mydomain.com/classes/Post
用户发布博客
向repos
路径发送一个POST
请求:
curl -X POST \
-d '{"username":"Wang Yibo\'s Fan", \
"title": "CoolGuyWangYibo", \
"content": "#王一博有翡# wyb #王一博谢允# 愿时光不负岁月, 愿世界不负温柔, 愿每一个善良的人都被认真对待, 千山万重, 不离不弃, 未来可期!@UNIQ-王一博"}' \
https://api.mydomain.com/repos
当创建成功时,HTTP返回为201 Created
,Location 头包含了新创建的博客的URL,例如:
Status: 201 Created
Location: https://api.mydomain.com/repos/Wyb/558e20cbe4b060308e3eb36c
返回的主体是一个 JSON 对象,包含 objectId,createdAt 时间戳表示创建对象时间:
{
"content": "#王一博有翡# wyb #王一博谢允# 愿时光不负岁月, 愿世界不负温柔, 愿每一个善良的人都被认真对待, 千山万重, 不离不弃, 未来可期!@UNIQ-王一博",
"pubUser": "Wang Yibo's Fan",
"createdAt": "2019-11-01 01:08:05",
"updatedAt": "2019-11-11 02:08:05",
"objectId": "558e20cbe4b060308e3eb36c"
}
用户删除博客
向repos
路径发送一个DELETE
请求,删除成功返回200
码,并返回一个JSON对象,例如:
curl -X DELETE \
https://api.mydomain.com/repos/Wyb/558e20cbe4b060308e3eb36c
HTTP/1.1 200 OK
Content-Type: application/json;charset=utf-8
...
{
"content": "#王一博有翡# wyb #王一博谢允# 愿时光不负岁月, 愿世界不负温柔, 愿每一个善良的人都被认真对待, 千山万重, 不离不弃, 未来可期!@UNIQ-王一博",
"pubUser": "Wang Yibo's Fan",
"createdAt": "2019-11-01 01:08:05",
"updatedAt": "2019-11-11 02:08:05",
"objectId": "558e20cbe4b060308e3eb36c"
}
关注/取关用户
- 关注用户
例如,让当前用户(objectId为51fa6886e4b0cc0b5a3792e9
)关注目标用户(objectId为51e3a334e4b0b3eb44adbe1a
)curl -X POST \ https://api.mydomain.com/users/51fa6886e4b0cc0b5a3792e9/friendship/51e3a334e4b0b3eb44adbe1a
- 取关用户
例如,让当前用户(objectId为51fa6886e4b0cc0b5a3792e9
)取消关注目标用户(objectId为51e3a334e4b0b3eb44adbe1a
)curl -X DELETE \ https://api.mydomain.com/users/51fa6886e4b0cc0b5a3792e9/friendship/51e3a334e4b0b3eb44adbe1a
用户查看粉丝/关注者列表
- 查询粉丝列表,也就是关注我(假设objectId为
51fa6886e4b0cc0b5a3792e9
)的人
curl -X GET \
https://api.mydomain.com/users/51fa6886e4b0cc0b5a3792e9/followers
- 查询关注者列表,也就是我(假设objectId为
51fa6886e4b0cc0b5a3792e9
)关注的人
curl -X GET \
https://api.mydomain.com/users/51fa6886e4b0cc0b5a3792e9/following
参考资料
博客-RESTful是什么,为什么要使用它
RESTful API 设计指南
Web API 设计
REST API使用详解
HTTP API设计指南