RESTful 风格的Api

概述

2000 年,是Roy Thomas Fielding博士于2000年在他的博士论文中提出来的一种万维网软件架构风格,目的是便于不同软件/程序在网络(例如互联网)中互相传递信息。表现层状态转换是根基于超文本传输协议HTTP之上而确定的一组约束和属性,是一种设计提供万维网络服务的软件构建风格。
他是一种风格。而不是规范。
简单理解:URL 定位资源,HTTP 动词(get post put patch delete)描述操作。

要点概述

  • 协议- API与用户的通信协议,总是使用HTTPs协议
  • 域名- 应该尽量将API部署在专用域名之下。
  • 版本- 应该将API的版本号放入URL。
  • 路径- 在RESTful架构中,每个网址代表一种资源(resource),所以网址中不能有动词,只能有名词,而且所用的名词往往与数据库的表格名对应。一般来说,数据库中的表都是同种记录的"集合"(collection),所以API中的名词也应该使用复数
  • HTTP动词- 对于资源的具体操作类型,由HTTP动词表示。
  • 过滤信息- 如果记录数量很多,服务器不可能都将它们返回给用户。API应该提供参数,过滤返回结果。例如:/path?limit=10:指定返回记录的数量
  • 状态码 -服务器向用户返回的状态码和提示信息。
  • 错误处理-如果状态码是4xx,就应该向用户返回出错信息。一般来说,返回的信息中将error作为键名,出错信息作为键值即可。
{
    error: "Invalid API key"
}
  • 返回结果
GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档
  • Hypermedia API -RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么

资源路径

RESTful Api 是依照资源为中心,每个url 代表一个资源,因此url 中不能有动词要有名词,形容词也可以使用但是要少用,不论资源是单数还是复数,API 中的表示资源的名词要用复数。此外,命名名词的时候,要依照字母数字下划线区分多个单词,这样设计,是为了和 json对象和属性命名方案保持一致

【GET】  /v1/tags/{tag_id} 
【POST】  /v1/users/{user_id}/roles/{role_id} // 添加用户的角色

当资源变化难依用标准的 restful api 命名的时候,可以考虑用一些特殊的单词 actions 命名

/{resources}/{resource_id}/actions/{action}
【PUT】  /v1/users/{user_id}/password/actions/modify // 密码修改

请求方式

可以通过 get post put patch delete 方式对服务端的资源进行操作。

  • GET:用于查询资源
  • POST:用于创建资源
  • PUT:用于更新服务端的资源的全部信息
  • PATCH:用于更新服务端的资源的部分信息
  • DELETE:用于删除服务端的资源。

查询参数

restful api 应该提供参数来过滤查询结果。

GET】  /{version}/{resources}/{resource_id}?offset=0&limit=20&orderby={field} [asc|desc]

状态码

使用合适的状态码很重要,不要所有的都返回200或者随便乱用。
HTTP 状态码就是一个三位数,分成五个类别。

1xx:相关信息
2xx:操作成功
3xx:重定向
4xx:客户端错误
5xx:服务器错误

HTTP 状态码-维基百科

问题: 当需要自定义的状态码又不属于那五个类别该怎么办??

异常响应

当出现非2xx http状态码的时,应采用全局的异常机构响应信息

HTTP/1.1 400 Bad Request
Content-Type: application/json
{
    "code": "INVALID_ARGUMENT",
    "message": "{error message}",
    "cause": "{cause message}",
    "request_id": "01234567-89ab-cdef-0123-456789abcdef",
    "host_id": "{server identity}",
    "server_time": "2014-01-01T12:00:00Z"
}

请求参数

在设计api 的时候,要对请求参数进行限制说明

【GET】     /v1/users/batch?user_ids=1001,1002      // 批量查询用户信息
参数说明
- user_ids: 用户ID串,最多允许 20 个。
---------------------------++++--------------------------------
【POST】     /v1/users                             // 创建用户信息
请求内容
{
    "username": "jack ma",                 // 必填, 用户名称, max 10
    "realname": "马云",               // 必填, 用户名称, max 10
    "password": "123456",              // 必填, 用户密码, max 32
    "email": "[email protected]",     // 选填, 电子邮箱, max 32
    "weixin": "alibaba",            // 选填,微信账号, max 32
    "sex": 1                           // 必填, 用户性别[1-男 2-女 99-未知]
}

响应参数

服务端返回结果如下:

【GET】     /{version}/{resources}/{resource_id}      // 返回单个资源对象
【GET】     /{version}/{resources}                    // 返回资源对象的列表
【POST】    /{version}/{resources}                    // 返回新生成的资源对象
【PUT】     /{version}/{resources}/{resource_id}      // 返回完整的资源对象
【PATCH】   /{version}/{resources}/{resource_id}      // 返回完整的资源对象
【DELETE】  /{version}/{resources}/{resource_id}      // 状态码 200,返回完整的资源对象。
                                                      // 状态码 204,返回一个空文档

怎么理解 RESTful API 的幂等性

HTTP 幂等方法 : 是指不论调用多少次都不会返回不同的结果的 HTTP方法。

功能 URL HTTP Method 幂等性
获取一组数据列表 /path/records GET 幂等
根据 ID 获取某笔数据 /path/records/{recordID} GET 幂等
新建数据 /path/records POST 非幂等
完整更新数据 /path/records/{recordID} PUT 幂等
部分更新数据 /path/records/{recordID} PATCH 非幂等
删除数据 /path/records/{recordID} DELETE 幂等
跨域访问预请求 /path/records/{recordID} DELETE

内容传输格式

RESTful 没有定义 Body 中内容传输的格式,有另外的规范来描述怎么设计 Body 的数据结构。
JSON 文档结构
在顶级节点使用 data、errors、meta,来描述数据、错误信息、元信息,注意 data 和 errors 应该互斥,不能再一个文档中同时存在,meta 在项目实际上用的很少,只有特别情况才需要用到,比如返回服务器的一些信息。

{
    "links": {
        "self": "http://example.com/articles",
        "next": "http://example.com/articles?page[offset]=2",
        "last": "http://example.com/articles?page[offset]=10"
    },
    "data": [
        {
            "type": "articles",
            "id": "1",
            "attributes": {
                "title": "JSON API paints my bikeshed!"
            },
            "relationships": {},
            "links": {
                "self": "http://example.com/articles/1"
            }
        }
    ],
    "included": [],
    "meta": {
        "version": "1.0.0",
        "copyright": "Copyright 2015 Example Corp."
    }
}

MIME 类型

JSON API 数据格式已经被 IANA 机构接受了注册,因此必须使用 application/vnd.api+json 类型。客户端请求头中 Content-Type 应该为 application/vnd.api+json,并且在 Accept 中也必须包含 application/vnd.api+json。如果指定错误服务器应该返回 415406 状态码。

data 属性

{
    "type": "articles",
    "id": "1",
    "attributes": {
        "title": "JSON API paints my bikeshed!"
    },
    "relationships": {},
    "links": {
        "self": "http://example.com/articles/1"
    }
}
  • id: 显而易见为唯一标识,可以为数字也可以为hash字符串,取决于后端实现
  • type: 描述数据的类型,可以对应为数据模型的类名
  • attributes: 代表资源的具体数据
  • relationships、links: 为可选属性,用来放置关联数据和资源地址等数据

errors 属性

{
    "errors": [
        {
            "code": 10011,
            "title": "Name can't be null"
        },
        {
            "code": 10011,
            "title": "Content can't be null",
            "detail": ""
        }
    ]
}

参考:
RESRful Api-维基百科
RESTful API 设计指南
RESTful API 最佳实践
通俗理解 RESTful api
json api 中文版
google Json风格指南
HTTP 状态码-维基百科
https://developer.github.com/v3/apps/permissions/
https://www.restapitutorial.com/

你可能感兴趣的:(RESTful 风格的Api)