Koa2实战练手(一)------ 学习RESTful API

Koa 是下一代的 Node.js 的 Web 框架。由 Express 团队设计。目的是提供一个更小型、更富有表现力、更可靠的 Web 应用和 API 的开发基础。
随着Nodejs新版本正式支持了async和await特性,Koa也当即在2017年2月发布了V2.0.0版本,咱们称之为Koa2。
为了紧跟潮流,咱们一块儿来经过一个实际的小项目来学习Koa2。html

1、项目设计

既然是为了完整的学习Koa2,确定不能只作一个“Hello world!”,咱们能够作一个“Hello Koa2!”。呵呵,言归正传。什么项目既足够小,又能完整的学习一个web框架了? 固然是框架最流行的"Hello world"项目:TODO应用。node

本次计划开发的TODO List应用使用先后端分离的设计,采用REST(Representational State Transfer)架构。REST是Roy Thomas Fielding在2000年的论文Architectural Styles and
the Design of Network-based Software Architectures
中提出的。git

2、学习REST

既然要采用REST架构,那么对REST咱们就须要有一个较全面的了解。github

2.1 REST设计原则

  1. 每一个URI表示一种资源(resource)
  2. URI应该使用名称而不是动词
  3. 使用复数名词
  4. GET方法不能改变状态
  5. HTTP协议中四种方法对应四种基本的操做:
    • GET: 获取资源(select)
    • POST:新建资源(create)
    • PUT:更新资源(update)
    • DELETE:删除资源(delete)
  6. 其余方法
    • HEAD:获取资源的元数据(meta data),例如数据的hash值或则资源的最后更新时间
    • OPTIONS:返回当前资源容许客户作哪些操做;
  7. 使用子资源表示关系
  8.  

2.二、协议

RESTful API与用户通信的协议,一采用HTTPS协议。(练手项目为了简单,就先采用HTTP协议)web

2.三、版本(Versioning)

有两种指明API版本的方法:express

A. 版本号放到HTTPS请求的头信息的Accept字段中:json

Accept: vnd.example-com.foo+json; version=1.0
Accept: vnd.example-com.foo+json; version=1.1
Accept: vnd.example-com.foo+json; version=2.0

#github采用以下的形式指明版本号
Accept: application/vnd.github.v3+json

B 将版本号放到URL中后端

https://api.example.com/v1/

#豆瓣API
https://api.douban.com/v2/book/isbn/:name

2.四、API根地址

尽可能将API部署在专用域名下。例如github和豆瓣的API就是部署在专用域名下。此种方式适用于应用比较复杂和庞大,在规模化时灵活性比较好。api

https://api.douban.com/v2/book/isbn/:name
https://api.github.com/
https://api.example.com

在简单的状况下,也能够将API部署到主域名之下。这样能够采用相同的框架同时支持站点和API。数组

https://example.org/api/

同时API的根返回API的相关说明是一个较好的实践。github的根API就是一个典型的例子。

2.5 端点(Root Endpoint)

一个端点就是指向特定资源或资源集合的URL。以构建一个虚拟的动物园的API为例,咱们有多个动物园,每一个动物园包含有多种的动物,员工,那么端点能够设计以下:

https://api.example.org/v1/zoos
https://api.example.org/v1/animals
https://api.example.org/v1/employees

2.6 HTTP动词

对具体资源的操做类型,由HTTP动词表示。

经常使用的HTTP动词有以下五个:

  • GET(SELECT): 获取资源
  • POST(CREATE):新建资源
  • PUT(UPDATE):更新资源(客户端提供改变后的完整资源)
  • PATCH(UPDATE):在服务器更新资源(客户端只提供改变的属性)
  • DELETE(DELETE):删除资源

不经常使用的还有以下的两个:

  • HEAD:获取资源的元数据(meta data),例如数据的hash值或则资源的最后更新时间
  • OPTIONS:返回当前资源容许客户作哪些操做;

仍是以动物园的API为例。对于每个端点,能够列出全部可行的HTTP动词和端点的组合。

GET /zoos: 列出全部动物
POST /zoos: 新建一个动物园
GET /zoos/ZID: 获取指定动物园的信息
PUT /zoos/ZID: 更新指定的动物园(提供该动物园的完整信息)
PATCH /zoos/ZID: 更新指定的动物园(提供该动物园的部分信息)
DELETE /zoos/ZID: 删除指定的动物园
GET /zoos/ZID/animals: 获取指定动物园的全部动物
DELETE /zoos/ZID/animals/AID: 删除指定动物园的指定动物
GET /zoos/ZID/employees: 列出指定动物园的全部雇员
POST /zoos/ZID/employees: 在指定动物园雇佣一个新雇员
DELETE /zoos/ZID/employees/EID: 从指定动物园解雇一个指定的雇员

2.7 过滤信息和分页(Filtering & Paging)

若是记录的数据量比较多,API就应该提供参数,对返回的结果进行过滤。经常使用的参数有以下一些:

#limit和offset就能实现分页
?limit=10:指定返回记录的数量
?offset=10:指定返回记录的开始位置。
?page=2&per_page=100:指定第几页,以及每页的记录数。


#为了将总数发给客户端,使用订制的HTTP头: X-Total-Count.
#连接到下一页或上一页能够在HTTP头的link规定,遵循Link规定:

Link: <https://blog.mwaysolutions.com/sample/api/v1/cars?offset=15&limit=5>; rel="next",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=50&limit=3>; rel="last",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=0&limit=5>; rel="first",
<https://blog.mwaysolutions.com/sample/api/v1/cars?offset=5&limit=5>; rel="prev",

2.8 排序(Sorting)

对返回的结果按照某个属性排序以及排序顺序。

?sortby=name&order=asc:指定返回结果按照哪一个属性排序,以及排序顺序。

#根据生产者降序和模型升序排列
?sort=-manufactorer,+model

2.9 字段选择(Field selection)

移动端可以显示其中一些字段,它们其实不须要一个资源的全部字段,给API消费者一个选择字段的能力,这会下降网络流量,提升API可用性。

#仅须要制造商,类型,id和颜色字段
?fields=manufacturer,model,id,color

2.10 状态码(Status Codes)

服务器向用户返回的状态码和提示信息,HTTP 1.1中常见的有如下一些(方括号中是该状态码对应的HTTP动词)。

200 OK - [GET]:服务器成功返回用户请求的数据,该操做是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:客户端要求服务器删除一个资源,服务器删除成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操做,该操做是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户获得受权(与401错误相对),可是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操做,该操做是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(好比用户请求JSON格式,可是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再获得的。
422 Unprocesable entity - [POST/PUT/PATCH] 当建立一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将没法判断发出的请求是否成功。

状态码范围(Status Code Ranges)

1xx  保留给底层HTTP功能使用
2xx  保留给成功消息使用
3xx  保留给重定向使用,通常API不会使用此类状态
4xx  保留给客户端错误使用。例如,客户端提供了一些错误的数据或请求了不存在的内容。这些请求应该是幂等的,不会改变任何服务器的状态。
5xx  保留给服务器端错误用的。这些错误经常是从底层的函数抛出来的,而且开发人员也一般无法处理。发送这类状态码的目的是确保客户端能获得一些响应。收到5xx响应后,客户端没办法知道服务器端的状态,因此这类状态码是要尽量的避免。

完整状态码列表能够参考RFC2616

2.11 返回结果

当使用不一样的HTTP动词向服务器请求时,客户端须要在返回结果里面拿到一系列的信息。下面的列表是很是经典的RESTful API定义:

GET /collection: 返回资源对象列表(数组)
GET /collection/resource: 返回单个的资源对象
POST /collection: 返回新建立的资源对象
PUT /collection/resource: 返回完整的资源对象
PATCH /collection/resource: 返回完整的资源对象
DELETE /collection/resource: 返回一个空文档

当一个客户端建立一个资源时,她们经常不知道新建资源的ID(也许还有其余的属性,如建立和修改的时间戳等)。这些属性将在随后的请求中返回,而且做为刚才POST请求的一个响应结果。

2.12 Hypermedia API

RESTful API最好作到Hypermedia,即返回结果中提供连接,连向其余API方法,使得用户不查文档,也知道下一步应该作什么。
好比,当用户向api.example.com的根目录发出请求,会获得这样一个文档。

{
    "link": {
        "rel": "collection https://www.example.com/zoos",
        "href": "https://api.example.com/zoos",
        "title": "List of zoos",
        "type": "application/vnd.yourformat+json"
    }
}

上面代码表示,文档中有一个link属性,用户读取这个属性就知道下一步该调用什么API了。rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址),href表示API的路径,title表示API的标题,type表示返回类型。
Hypermedia API的设计被称为HATEOAS。Github的API就是这种设计,访问api.github.com会获得一个全部可用API的网址列表。

{
  "current_user_url": "https://api.github.com/user",
  "authorizations_url": "https://api.github.com/authorizations",
  // ...
}

从上面能够看到,若是想获取当前用户的信息,应该去访问api.github.com/user,而后就获得了下面结果。

{
    "message": "Requires authentication",
    "documentation_url": "https://developer.github.com/v3"
}

上面代码表示,服务器给出了提示信息,以及文档的网址。

项目已经发布到github: koa-todo

参考文章:
阮一峰 RESTful API 设计指南

做者:Q_幽兰_Q 连接:https://www.jianshu.com/p/c37a13506753 來源:简书 著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。

相关文章
相关标签/搜索