Sevice Computing:模仿 Github设计一个博客网站的 API
一、名词解释:API & REST
什么是API?
API是Application Programming Interface(应用程序接口)的缩写,它是拿来描述一个类库的特征或是如何去运用它。
什么是REST?
REST是Representational State Transfer(表现层状态转移)的缩写,它是由罗伊·菲尔丁(Roy Fielding)在2000年提出的软件软件架构模式,是用来描述创建HTTP API的标准方法的。
REST(Representational State Transfer)是Roy Fielding博士在2000年提出的软件软件架构模式。REST 是一种风格,而不是标准。因为既没有 REST RFC,也没有 REST 协议规范或者类似的规定。它只是提供了一组设计原则和约束条件,主要用于客户端和服务器交互类的软件。Roy Fielding 把 REST 定义成一种架构风格,其目标是“使延迟和网络交互最小化,同时使组件实现的独立性和扩展性最大化”。
二、理解 Github API
通过网址https://api.github.com/users/用户名
中我们可以看到关于用户个人的所有信息
下图为输入https://api.github.com/users/ZhengweiZhao
后获取到的我的GitHub信息:
{
"login": "ZhengweiZhao",
"id": 55046922,
"node_id": "MDQ6VXNlcjU1MDQ2OTIy",
"avatar_url": "https://avatars1.githubusercontent.com/u/55046922?v=4",
"gravatar_id": "",
"url": "https://api.github.com/users/ZhengweiZhao",
"html_url": "https://github.com/ZhengweiZhao",
"followers_url": "https://api.github.com/users/ZhengweiZhao/followers",
"following_url": "https://api.github.com/users/ZhengweiZhao/following{/other_user}",
"gists_url": "https://api.github.com/users/ZhengweiZhao/gists{/gist_id}",
"starred_url": "https://api.github.com/users/ZhengweiZhao/starred{/owner}{/repo}",
"subscriptions_url": "https://api.github.com/users/ZhengweiZhao/subscriptions",
"organizations_url": "https://api.github.com/users/ZhengweiZhao/orgs",
"repos_url": "https://api.github.com/users/ZhengweiZhao/repos",
"events_url": "https://api.github.com/users/ZhengweiZhao/events{/privacy}",
"received_events_url": "https://api.github.com/users/ZhengweiZhao/received_events",
"type": "User",
"site_admin": false,
"name": null,
"company": null,
"blog": "",
"location": null,
"email": null,
"hireable": null,
"bio": null,
"public_repos": 14,
"public_gists": 0,
"followers": 0,
"following": 0,
"created_at": "2019-09-08T08:39:16Z",
"updated_at": "2019-10-26T12:48:52Z"
}
其中包括很多xxx_url这些是查询其他部分信息的地址,比如
- 获取个人所有repo
输入url https://api.github.com/users/用户名/repos
会得到一个repo的JSON格式列表,如下图所示:
三、REST API 设计原则
HTTP 协议定义了大量为请求赋于语义的方法。API访问都是通过HTTPS协议进行的,并通过https://api.blog.com
进行访问,数据以JSON的形式发送和接收。
使用 HTTP 设计 RESTful API 时的一些主要原则:
- REST API 围绕资源设计,资源是可由客户端访问的任何类型的对象、数据或服务。
- 每个资源有一个标识符,即,唯一标识该资源的 URI。
- 客户端通过交换资源的表示形式来与服务交互。 许多 Web API 使用 JSON 作为交换格式。
- REST API 使用统一接口,这有助于分离客户端和服务实现。 对于基于 HTTP 构建的 REST API,统一接口包括使用标准 HTTP 谓词对资源执行操作。 最常见的操作是 GET、POST、PUT、PATCH 和 DELETE。
- REST API 使用无状态请求模型。 HTTP 请求应是独立的并可按任意顺序发生,因此保留请求之间的瞬时状态信息并不可行。 信息的唯一存储位置就在资源内,并且每个请求应是原子操作。
- REST API 由表示形式中包含的超媒体链接驱动。
基本操作:
-
GET
GET 检索位于指定 URI 处的资源的表示形式。 响应消息的正文包含所请求资源的详细信息。
成功的 GET 方法通常返回 HTTP 状态代码 200(正常)。 如果找不到资源,该方法应返回 404(未找到)。 -
POST
POST 在指定的 URI 处创建新资源。服务器为新资源分配 URI,并将该 URI 返回给客户端。 在 REST 模型中,我们经常向集合应用 POST 请求。 新资源将添加到集合中。 还可以使用 POST 请求将待处理数据提交到现有资源,且不创建任何新资源。 请求消息的正文将提供新资源的详细信息。 请注意,POST 还用于触发不实际创建资源的操作。 -
PUT
PUT 在指定的 URI 处创建或替换资源。请求消息的正文指定要创建或更新的资源。客户端指定资源的 URI。请求正文包含资源的完整表示形式。 如果已存在具有此 URI 的资源,则替换该资源。 否则创建新资源(如果服务器支持此操作)。 PUT 请求往往应用到单项资源(例如特定的客户)而不是集合。 -
PATCH
PATCH 对资源执行部分更新。 请求正文包含要应用到资源的一组更改。 客户端指定资源的 URI。这比使用 PUT 更高效,因为客户端只发送更改,而无需发送资源的整个表示形式。 -
DELETE
-
DELETE 删除位于指定 URI 处的资源。
错误名称及描述:
HTTP verbs:
四、博客网站的 API设计
1. 当前版本
Accept: application/vnd.myblog.v3+json
2. 概要
- API访问都是通过HTTPS协议进行的,并通过
https://api.myblog.com
进行访问,数据以JSON的形式发送和接收。 - 我们假设当前用户为zzw
curl -i https://api.myblog.com/users/zzw
HTTP/1.1 200 OK
Server: nginx
Date: Tue, 19 Nov 2019 23:33:14 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
Status: 200 OK
ETag: "a00049ba79152d03380c34652f2cb612"
X-GitHub-Media-Type: myblog.v3
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4987
X-RateLimit-Reset: 1350085394
Content-Length: 5
Cache-Control: max-age=0, private, must-revalidate
X-Content-Type-Options: nosniff
- 空白字段不会被忽略而会显示null。
- 所有时间戳以ISO 8601 format被返回:
YYYY-MM-DDTHH:MM:SSZ
3. 基本操作
-
GET
在获取所有blog的列表时,响应包含该blog的属性子集。这是blog的“摘要”表示。
获取所有的blog的URL如下所示:GET /user/zzw/blogs
在获取单个博客时,响应通常包括该博客的所有属性。这是资源的“详细”表示。
获取某个指定的blog,例如,名为helloworld的blog,其URL如下:GET /user/zzw/blog/helloworld
GET可用于用户信息:
GET /user/:username
-
POST
新建blog使用POST请求,URL如下:POST /user/zzw/newblog
-
PUT
更新一篇文章,如newblog时,使用PUT请求,其URL如下:PUT /user/zzw/blogs/newblog
(因为一篇博客的局部更新和GitHub一个repo的部分文件更新不同,所以这里将PATCH功能删除了,我认为PUT就足够了)
-
DELETE
删除一篇文章使用DELETE请求,例如,删除名称为helloworld的文章,其URL如下:DELETE /example/articles/helloworld
4. 参数
许多API方法采用可选参数。对于GET请求,任何未在路径中指定为段的参数都可以作为HTTP查询字符串参数传递:
curl -i "https://api.myblog.com/blogs/zzw/helloworld/issues?state=closed"
其中,zzw是user的参数,helloworld是blog的参数,:state传递路径参数。
对于POST、PATCH、PUT和DELETE请求,URL中没有包含的参数,应该用“application/ JSON”的内容类型编码为JSON:
curl -i -u username -d '{"scopes":["public_repo"]}' https://api.myblog.com/authorizations
5. 身份认证
有两种方法可以进行身份验证。需要身份验证的请求在某些地方将返回404 Not Found
,而不是403 Forbidden
。这是为了防止私有存储库意外泄漏给未经授权的用户。
- 基本认证
curl -u "username" https://api.myblog.com
- OAuth2 token (sent in a header)
curl -H "Authorization: token OAUTH-TOKEN" https://api.myblog.com
6. 错误信息
- 400
发送无效或错误类型的JSON将导致400 Bad Request响应:HTTP/1.1 400 Bad Request Content-Length: 35 {"message":"Problems parsing JSON"}
HTTP/1.1 400 Bad Request Content-Length: 40 {"message":"Body should be a JSON object"}
- 401
使用无效凭据进行身份验证将返回401未经授权:curl -i https://api.myblog.com -u foo:bar HTTP/1.1 401 Unauthorized { "message": "Bad credentials", "documentation_url": "https://developer.myblog.com/v3" }
- 403
在短时间内检测到多个具有无效凭据的请求后,API会暂时拒绝该用户的所有身份验证尝试(包括具有有效凭据的请求),并设置403禁止:curl -i https://api.myblog.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.myblog.com/v3" }
- 422
发送无效的字段将导致422 Unprocessable Entity响应:HTTP/1.1 422 Unprocessable Entity Content-Length: 149 { "message": "Validation Failed", "errors": [ { "resource": "Issue", "field": "title", "code": "missing_field" } ] }
7. 分页
默认情况下,返回多个条目的请求将被分页为30个条目。可以使用?page
参数指定其他页面。对于某些资源,还可以使用?per_page
参数将自定义页面大小设置为100。
curl 'https://api.myblog.com/user/zzw/blogs?page=2&per_page=100'
8. 链接标题
链接标题包含分页信息:
Link: <https://api.myblog.com/user/zzw/blogs?page=3&per_page=100>; rel="next",
<https://api.myblog.com/user/zzw/blogs?page=50&per_page=100>; rel="last"