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


相关推荐

  • C语言读取txt文件实例

    C语言读取txt文件实例本文主要总结用C语言来读txt文本的内容,具体的步骤如下所述。1.1建一个.c源文件,赋值如下代码。#include<stdio.h>#include<stdlib.h>#include<string.h>#defineMAX_LINE1024intmain(){charbuf[MAX_LINE];/*缓冲区*/FILE*fp;…

    2022年6月2日
    218
  • Word2vec之CBOW模型和Skip-gram模型形象解释「建议收藏」

    Word2vec之CBOW模型和Skip-gram模型形象解释「建议收藏」Word2vec中两个重要模型是:CBOW和Skip-gram模型这里主要讲下我本人对CBOW模型的理解,这是主要是举个例子简化下首先说下CBOW的三层结构:输入层,投影层(中间层),输出层假设语料库有10个词:【今天,我,你,他,小明,玩,北京,去,和,好】现在有这样一句话:今天我和小明去北京玩很显然,对这个句子分词后应该是:今天我和小明去北京玩对于小明而言,选择他的前

    2025年8月27日
    6
  • 分区容错性和可用性的区别

    分区容错性和可用性的区别分区容错性:因为网络等硬件引起的问题,一台服务器崩溃了,保证能在其他服务器上也能顺利完成业务。可用性:因为软件代码层面的问题,一台服务器上的服务崩溃了,保证能在其他服务器上完成该业务。区别:分区容错性更偏向于硬件引起的问题可用性更偏向于软件代码层面的问题…

    2022年7月25日
    25
  • SpringCloud2.0

    SpringCloud2.0

    2021年7月3日
    98
  • 前端常见跨域解决方案[通俗易懂]

    前端常见跨域解决方案[通俗易懂]前端常见跨域解决方案

    2022年4月22日
    38
  • 使用xsync脚本分发「建议收藏」

    使用xsync脚本分发「建议收藏」为什么使用xsync脚本来分发文件因为操作简单,只需要执行脚本在后面加上需要分发的文件就行了然后底层不一致,scp使用的是安全拷贝,而xsync使用的是增量拷贝由于底层不一致,xsync比scp快上许多使用脚本来分发文件之前不同节点之间的免密登录安排上脚本实现#!/bin/bash#1输入参数个数,如果没有参数就会退出pcount=$#if((pcount==0));thenechonoargs;exit;fi#2需要分发的文件名称p1=$1fname=`

    2022年5月18日
    53

发表回复

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

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