RESETful API 设计规范

RESETful API 设计规范

RESTful 是目前最流行的 API 设计规范,用于 Web 数据接口的设计

关于「能愿动词」的使用

为了避免歧义,文档大量使用了「能愿动词」,对应的解释如下:

  • 必须 (MUST):绝对,严格遵循,请照做,无条件遵守;
  • 一定不可 (MUST NOT):禁令,严令禁止;
  • 应该 (SHOULD) :强烈建议这样做,但是不强求;
  • 不该 (SHOULD NOT):强烈不建议这样做,但是不强求;
  • 可以 (MAY)可选 (OPTIONAL) :选择性高一点,在这个文档内,此词语使用较少;
    参见:RFC 2119

域名

API 的根入口点应尽可能保持足够简单,这里有两个常见的 URL 根例子:

    https://api.example.com/* 
    
    https://example.com/api/*   

如果你的应用很庞大或者你预计它将会变的很庞大,那 应该 将 API 放到子域下(api.example.com)。这种做法可以保持某些规模化上的灵活性。

客户端请求

API 返回的数据格式,不应该是纯文本,而应该是一个 JSON 对象,因为这样才能返回标准的结构化数据。所以,客户端希望服务器回应的 HTTP 头的Content-Type属性要设为application/json。


GET /users/2 HTTP/1.1 
Accept: application/json
Content-Type: application/json
    

版本控制

所有的 API 必须保持向后兼容,你 必须 在引入新版本 API 的同时确保旧版本 API 仍然可用。所以 应该 为其提供版本支持。

目前比较常见的两种版本号形式:

  • 在 URL 中嵌入版本编号

    https://api.example.com/v1/*
    https://api.example.com/v2/*
  • 将版本号放在 HTTP Header 头中 通过媒体类型来指定版本信息

        Accept: application/vnd.example.com.v1+json

HTTP 动词

HTTP 请求动词通常就是五种方法,对应 CRUD 操作。

  • GET(SELECT):从服务器取出资源(一项或多项)。
  • POST(CREATE):在服务器新建一个资源。
  • PUT(UPDATE):在服务器更新资源(客户端提供改变后的完整资源)。
  • PATCH(UPDATE):在服务器更新资源(客户端提供改变的属性)。
  • DELETE(DELETE):从服务器删除资源。

针对每一个端点来说,下面列出所有可行的 HTTP 动词和端点的组合

用 URL 定位资源

请求方法 URL 描述
GET /zoos 列出所有的动物园(ID和名称,不要太详细)
POST /zoos 新增一个新的动物园
GET /zoos/{zoo} 获取指定动物园详情
PUT /zoos/{zoo} 更新指定动物园(整个对象)
PATCH /zoos/{zoo} 更新动物园(部分对象)
DELETE /zoos/{zoo} 删除指定动物园
GET /zoos/{zoo}/animals 检索指定动物园下的动物列表(ID和名称,不要太详细)
GET /animals 列出所有动物(ID和名称)。
POST /animals 新增新的动物
GET /animals/{animal} 获取指定的动物详情
PUT /animals/{animal} 更新指定的动物(整个对象)
PATCH /animals/{animal} 更新指定的动物(部分对象)
GET /animal_types 获取所有动物类型(ID和名称,不要太详细)
GET /animal_types/{type} 获取指定的动物类型详情
GET /employees 检索整个雇员列表
GET /employees/{employee} 检索指定特定的员工
GET /zoos/{zoo}/employees 检索在这个动物园工作的雇员的名单(身份证和姓名)
POST /employees 新增指定新员工
POST /zoos/{zoo}/employees 在特定的动物园雇佣一名员工
DELETE /zoos/{zoo}/employees/{employee} 从某个动物园解雇一名员工

超出
Restful 端点的,
应该 模仿上表的方式来定义端点。

资源过滤

如果记录数量很多,服务器不可能都将它们返回给用户。API
应该 提供参数,过滤返回结果。下面是一些常见的参数。

  • ?page=10:指定返回记录的数量
  • ?per_page=10:指定返回记录的开始位置。
  • ?page=2&per_page=100:指定第几页,以及每页的记录数。
  • ?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序。
  • ?status=closed:指定筛选条件

所有 URL 参数 必须 是全小写,必须 使用下划线类型的参数形式。

分页参数
必须 固定为
page
per_page

经常使用的、复杂的查询 应该 标签化,降低维护成本。如

GET /trades?status=closed&sort=sortby=name&order=asc

返回码

20x

200 OK

201 Created

对创建新资源的 POST 操作进行响应。应该带着指向新资源地址的 Location 头
  

202 Accepted

服务器接受了请求,但是还未处理,响应中应该包含相应的指示信息,告诉客户端该去哪里查询关于本次请求的信息

204 No Content

对不会返回响应体的成功请求进行响应(比如 DELETE 请求)

3xx 重定向

40x 客户端错误

400 Bad Request

请求异常,比如请求中的body无法解析

401 Unauthorized

没有进行认证或者认证非法或失效

403 Forbidden

服务器已经理解请求,但是拒绝执行它

404 Not Found

该状态码表示用户请求的资源不存在,如

  • 获取不存在的用户信息 (get /users/9999999)
  • 访问不存在的端点

必须 返回该状态码,若该资源已永久不存在,则 应该 返回 410 响应。

405 Method Not Allowed

所请求的 HTTP 方法不允许当前认证用户访问

409 Gonfilct

该状态码表示因为请求存在冲突无法处理。
如通过手机号码提供注册功能的 API,当用户提交的手机号已存在时,必须 返回此状态码。

410 Gone

表示当前请求的资源已永久不存在。当调用老版本 API 的时候很有用

413 Request Entity Too Large

该状态码表示服务器拒绝处理当前请求,因为该请求提交的实体数据大小超过了服务器愿意或者能够处理的范围。

此种情况下,服务器可以关闭连接以免客户端继续发送此请求。

如果这个状况是临时的,服务器 应该 返回一个 Retry-After 的响应头,以告知客户端可以在多少时间以后重新尝试。

414 Request-URI Too Long

该状态码表示请求的 URI 长度超过了服务器能够解释的长度,因此服务器拒绝对该请求提供服务。

415 Unsupported Media Type

通常表示服务器不支持客户端请求首部 Content-Type 指定的数据格式。如在只接受 JSON 格式的 API 中放入 XML 类型的数据并向服务器发送,都 应该 返回该状态码。

该状态码也可用于如:只允许上传图片格式的文件,但是客户端提交媒体文件非法或不是图片类型,这时 应该 返回该状态码:

HTTP/1.1 415 Unsupported Media Type
Server: nginx/1.11.9
Content-Type: application/json
Transfer-Encoding: chunked
Cache-Control: no-cache, private
Date: Sun, 24 Jun 2018 12:09:40 GMT
Connection: keep-alive

{"error_code":41500,"message":"不允许上传的图片格式"}

422 Unprocessable Entity

用来表示校验错误
{
    "message": "422 Unprocessable Entity",
    "errors": {
        "name": [
            "姓名 必须为字符串。"
        ]
    },
    "status_code": 422
}

429 Too Many Requests

该状态码表示用户请求次数超过允许范围。如 API 设定为 60次/分钟,当用户在一分钟内请求次数超过 60 次后,都 应该 返回该状态码。并且也 应该 在响应首部中加上下列头部:

X-RateLimit-Limit: 10 请求速率(由应用设定,其单位一般为小时/分钟等,这里是 10次/5分钟)
X-RateLimit-Remaining: 0 当前剩余的请求数量
X-RateLimit-Reset: 1529839462 重置时间
Retry-After: 120 下一次访问应该等待的时间(秒)

列子

必须 为所有的 API 设置 Rate Limit 支持。

50x 服务器错误

500 Internal Server Error

503 Service Unavailable

数据响应格式

错误格式

对于错误数据,默认使用如下结构:

'message' => ':message',          // 错误的具体描述
'errors' => ':errors',            // 参数的具体错误描述,422 等状态提供
'code' => ':code',                // 业务自定义的异常码
'status_code' => ':status_code',  // http状态码
'debug' => ':debug',              // debug 信息,非生产环境提供

422错误码显示


HTTP/1.1 422 Unprocessable Entity
Content-Type: application/json

{
    "message": "422 Unprocessable Entity",
    "errors": {
        "username": [
            "姓名 必须为字符串。"
            "姓名 必须介于 4 - 18 个字符之间"
        ],
        "phone": [
            "手机号码 格式不正确。"
        ]
    },
    "status_code": 422
}

403错误码显示

HTTP/1.1 403 Forbidden
Content-Type: application/json

{
    "message": "您无权访问该订单",
    "status_code":"403"
}

429错误码显示

HTTP/1.1 429 Too Many Requests
Server: nginx/1.11.9
Content-Type: application/json
Transfer-Encoding: chunked
X-RateLimit-Limit: 10
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1529839462
Retry-After: 290
Cache-Control: no-cache, private
Date: Sun, 24 Jun 2018 11:19:32 GMT
Connection: keep-alive

{
    "message":"You have exceeded your rate limit.",
    "status_code":429
}

正确输出显示

分页显示

{
    "data": [
        {
            "id": 1,
            "name": "Eladio Schroeder Sr.",
            "email": "therese28@example.com",
        },
        {
            "id": 2,
            "name": "Liliana Mayert",
            "email": "evandervort@example.com",
        }
    ],
    "links":{
        "first": "http://example.com/pagination?page=1",
        "last": "http://example.com/pagination?page=1",
        "prev": null,
        "next": null
    },
    "meta":{
        "current_page": 1,
        "from": 1,
        "last_page": 1,
        "path": "http://example.com/pagination",
        "per_page": 15,
        "to": 10,
        "total": 10
    }
}
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/101262.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 原码反码补码的相互转换_补码转化为反码

    原码反码补码的相互转换_补码转化为反码原码反码补码的相互转换原码反码补码的转换还是比较简单基础的问题。之前学习java的时候就学过,后来忘记了,忘记了!!!,后来学了位移运算符,左移右移无符号右移之后就由有点儿懵了。原码,反码,补码二进制中第一位是符号位,0表示正数,1表示负数。以八位二进制数为例。原码十进制数正1的二进制原码[+1]原=00000001十进制数负1的二进制原码[-1]原…

    2022年10月29日
    0
  • git clone 指定分支 拉代码

    git clone 指定分支 拉代码gitclone指定分支拉代码

    2022年5月29日
    86
  • 成功的草根网站_草根网 真看不懂

    成功的草根网站_草根网 真看不懂 如果你是菜鸟站长,如果你可以耐心的看完这篇文章,那么你的网站建设道路会少一些磕拌,多一些平坦.以上两个如果若不满足可以直接回主版面了.  首先声明一下,我也是菜鸟,虽然接触网站制作很久了,从2000年开始的,但中途做做停停,耽误了太多的时间,所以到现在我也只是个菜鸟,充其量只是个老菜鸟吧.但正因为我也是菜鸟,所以我说的东西都是些浅显易懂的,应该会对各位新手有些帮助吧,至少是少走很多弯路!

    2022年10月18日
    0
  • matlab安装包

    matlab安装包1.导入路径——保存2.compile——windows

    2022年6月11日
    26
  • 静态分析的四种基本方法是_比较静态均衡分析方法

    静态分析的四种基本方法是_比较静态均衡分析方法*数据流分析(DataFlowAnalysis)将数据看作是图,节点是程序的基本快,边是描述控制如何从一个基本快转移掉另一个基本快。图可以解决很多问题,例如:以图中边的抽象得出数学方程,七届就

    2022年8月4日
    5
  • Java反射 数组

    Java反射 数组

    2022年3月13日
    55

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号