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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 八皇后问题详解(四种解法)[通俗易懂]

    八皇后问题详解(四种解法)[通俗易懂]如果你去百度百科八皇后这个问题,你会发现人家也是历史上有头有脸的一个问题,最后一句“计算机发明后就有一万种方式解决这个问题”读起来也让程序猿们很快活。闲话少说,开始阐述我的思路:最无脑的解法一定是八个for遍历,浪费了太多的计算资源在各种无用功上面,我们稍微构思一下:首先如何决定下一个皇后能不能放这里可以有两种思路,第一种是尝试维护一个8*8的二维矩阵,每次找到一个空位放下一个皇后就把对应行列对

    2022年6月30日
    27
  • java中lambda表达式[通俗易懂]

    java中lambda表达式[通俗易懂]Java8(JDK1.8)中加入的lambda表达式Lambda的使用前提使用Lambda必须具有接口,且要求接口中有且仅有一个抽象方法。无论是JDK内置的Runnable、Comparator接口还是自定义的接口,只有当接口中的抽象方法存在且唯一时,才可以使用Lambda。使用Lambda必须具有上下文推断。也就是方法的参数或局部变量类型必须为Lambda对应的接口类型,才…

    2022年7月8日
    28
  • mac idea 2021激活码【2021免费激活】

    (mac idea 2021激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.htmlS32PGH0SQB-eyJsaWNlbnNlSWQi…

    2022年3月26日
    52
  • jmap的使用以及内存溢出分析

    jmap的使用以及内存溢出分析jmap 的使用以及内存溢出分析 jmap java 内存映像工具 jmap MemoryMapfor 命令用于生成堆转储快照 一般称为 heapdump 或 dump 文件 还有几种方式获取 dump 文件 使用 JVM 参数选项 XX HeapDumpOnOu 参数 可以让虚拟机在 OOM 异常出现之后自动生成 dump 文件 通过 XX HeapDumpPath path 设置 dump 文件路径 有时候 dump 文件比较大的时候可能无法自动导出 这时候就需要使用 jmap dump 手动导

    2025年12月6日
    4
  • markdown数学公式(常用版介绍)

    markdown数学公式(常用版介绍)

    2020年11月8日
    219
  • Python数组的使用_算法高效性

    Python数组的使用_算法高效性如果我们需要一个只包含数字的列表,那么使用数组方式比list方式更高效。而且数组还支持所有跟可变序列有关的操作,比如移除列表中的一个元素(.pop)、插入元素(.insert)和在列表末尾一次性追加另一个序列中的多个值(.extend)。除此之外,数组还定义从文件读取(.frombytes)与写入(.tofile)的效率更高的方法。创建数组需要一个类型码,形如array(‘d’),这个类型码是用来表示在底层实现的C语言的数据类型。一般我们用的Python底层是用C语言编写实现的&n

    2022年8月13日
    5

发表回复

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

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