• RESTful 接口设计规范-个人总结


    RESTful 接口设计规范-个人总结

    以下接口规范为个人收集并总结,仅供参考。欢迎提供建议

    使用名词,使用HTTP 请求方法

    接口中不要出现动词,以及动作。

    使用HTTP 请求方法作为动作的表达。常见的CRUD,在HTTP 中都有对应的方法,可参考https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods

    HTTP 请求方法

    表格来自:https://www.runoob.com/http/http-methods.html

    方法描述
    GET请求指定的页面信息,并返回实体主体。
    HEAD类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头
    POST向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。
    PUT从客户端向服务器传送的数据取代指定的文档的内容。
    DELETE请求服务器删除指定的页面。
    CONNECTHTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。
    OPTIONS允许客户端查看服务器的性能。
    TRACE回显服务器收到的请求,主要用于测试或诊断。
    PATCH是对 PUT 方法的补充,用来对已知资源进行局部更新 。

    有以下几种:GETPOSTPUTDELETEPATCH。与资源相关联的端点的名称必须与应用的操作相关的HTTP方法对应。

    // bad case
    GET /get_users
    POST /insert_users
    PUT /modify_users
    DELETE /delete_users
    
    // good case
    GET /users
    POST /users
    PUT /users
    DELETE /users
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    日常开发中不一定能保证完全按照HTTP 请求方法的规范,但至少要保证请求方法使用GET,其他使用POST

    全部小写

    RFC 3986 将 URI 定义为区分大小写,对于不同环境,大小写 URI 代表不同的路径,为了避免混淆,建议在 URI 中应始终使用小写字母。

    // bad case
    /Users/12345
    
    // good case
    /users/12345
    
    • 1
    • 2
    • 3
    • 4
    • 5

    使用斜杠 / 表示层次关系

    斜杠/ 通常用于资源的所属关系,后面的属于前面的。这点类似面相对象语言中的.

    例如:/users/{userId}/address/{userId}属于usersaddress属于{userId}

    使用连字符 - 提高可读性

    如果有多个单词,首先建议是使用/来区分层级关系,如果无法做到,则建议使用-区分

    // bad case
    /users/{userId}/pendingorders
    
    // good case
    /users/{userId}/pending-orders
    
    • 1
    • 2
    • 3
    • 4
    • 5

    不要使用下划线_

    虽然可以用下划线_ 代替连字符 - 作为分隔符,但有些应用程序的字体,下划线 _ 字符可能会在某些浏览器或屏幕中部分被遮住或完全遮住。

    为避免这种混淆,建议使用连字符 - 而不是下划线 _

    // bad case
    /users/{userId}/pending_orders
    
    // good case
    /users/{userId}/pending-orders
    
    • 1
    • 2
    • 3
    • 4
    • 5

    不用扩展名

    除非直接访问文件,或者下载文件,否则不要使用文件扩展名(例如.xlsx

    如果需要指定内容的格式,建议使用Content-Type

    // bad case
    /users/{userId}/pending-orders.xlsx
    
    // good case
    /users/{userId}/pending-orders
    Content-Type:application/vnd.ms-excel;charset=utf-8;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    单数还是复数

    如果能唯一确定的资源,则用单数,如果不能,则用复数。

    如果单复数都行的,则用复数,因为单数也是复数的特殊形式,为了保持兼容与统一,所以建议复数。

    // bad case
    GET /user/{userId}
    GET /users?sex=man
    
    // good case
    GET /users/{userId}
    GET /users/{userId}/address
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    精简

    减少无用信息,提高信息密度,

    // bad case
    GET /service/api/search
    
    // good case
    GET /search
    
    • 1
    • 2
    • 3
    • 4
    • 5

    不要暴露服务器的技术栈

    技术栈包括使用了服务器、中间件、开发语言以及目录和系统结构等。这些建议不要暴露出来,一方面是有安全隐患,另一方面接口使用方也不关心,冗余不符合精简原则

    // bad case
    /cgi-bin/get_user.php?user=100
    
    // good case
    /users?user=100
    
    • 1
    • 2
    • 3
    • 4
    • 5

    多条件查询(搜索)

    多条件查询时,要求使用?拼接参数查询

    例如:/users?location=shenzhen&sex=man 查找位于 shenzhen 的并且sex=man的所有用户

    到底用时/还是?

    • 只有一个筛选条件,并且能唯一确定对象,则用/,比如/users/{userId}
    • 有多个筛选条件,并且不能唯一确定对象,尤其是多条件搜索的情况,就用?比如/users?sex=man

    注意:只有一个筛选条件时,这里说的唯一,不仅包括单一对象,也包括集合

    比如

    • URL“/users/2023/”返回的页面为2023年的存档
    • URL“/users/2023/10/”返回的页面为2023年10月的存档
    // bad case
    GET /users/id={userId}
    GET /users/{userId}?sex=man
    
    // good case
    GET /users/{userId}
    GET /users?localtion=shenzhen&sex=man
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    例子

    // 单个条件,唯一确定
    https://www.zhihu.com/people/zhihusucks
    https://space.bilibili.com/11083481
    https://weibo.com/3266943013
    
    // 多个条件(搜索)
    https://www.zhihu.com/search?q=123&type=content
    https://www.zhihu.com/search?q=123&type=people
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    分页与排序支持

    分页与排序也当做筛选条件放在?后面

    • GET /users?limit=10&offset=0 :分页,从0行开始返回10条。
    • GET /users?limit=10&offset=0&sort=asc&order=title :排序,返回按名称升序排列的文章记录。

    如何表示列表

    当没有层次关系时(如在列表中),应该使用分号之类的标点符号或者常见的逗号。

    例如:/users/{id1},{id2} 访问多个用户资源。

    前端路由与域名相同问题

    有时候前端的路由地址会与后端的接口相同,会造成困扰、无法区分到底是前端路由还是后端的接口,调试的时候也会很麻烦。

    所以建议有两种方案,后端接口后者统一加/api/,或者后端提供的接口统一使用二级域名api.xx.com

    状态码

    众所周知,HTTP有自己的状态码,比如下述列表,那我们自己的业务的错误码或者状态码,应该直接复用HTTP的状态码,还是自定义呢?

    HTTP 状态码分类

    表格来源:https://www.runoob.com/http/http-status-codes.html

    HTTP 响应状态码由三个数字组成,第一个数字定义了状态码的类型。

    响应分为五类:信息响应(100–199),成功响应(200–299),重定向(300–399),客户端错误(400–499)和服务器错误 (500–599):

    分类分类描述
    1**信息,服务器收到请求,需要请求者继续执行操作
    2**成功,操作被成功接收并处理
    3**重定向,需要进一步的操作以完成请求
    4**客户端错误,请求包含语法错误或无法完成请求
    5**服务器错误,服务器在处理请求的过程中发生了错误

    结论:业务异常不要使用HTTP的状态码,而要统一放在HTTP 200状态码下面,使用自定义的业务状态码。原因如下

    下述结论大部分来自:

    https://www.zhihu.com/question/513865370/answer/2643896815

    https://www.zhihu.com/question/310737821/answer/585641618

    如果业务状态码使用HTTP的状态码,那么会有如下问题

    排查困难、分工混乱:一般HTTP的错误码(比如404)都是由服务器或者框架层面抛出的,并且大部分公司的运维与业务开发是分开的,运维只关心服务器层面的异常,业务开发只关心业务异常。如果不区分状态码,那么出现一个404的异常,就无法一眼看出来到底是谁的职责,还得进一步爬log,看错误信息才能确定问题,排查问题困难。如果区分的很清楚,则HTTP状态码的问题直接找运维,自定义的业务异常则直接找业务开发,再具体点就是HTTP200的异常去找业务开发,非HTTP200找运维。

    扩展性差:HTTP那点状态码支撑不起众多的业务场景,比如404表示找不到,业务中存在多种找不到的情况,比如“用户找不到”、“订单找不到”、“商品找不到”等情况,如果都用404,那排查问题还是很困难。

    运营商劫持:非200状态码(比如404、500)可能会被运营商劫持。或者其他开发人员除了200之外的状态码不认识,还有反向代理或者CDN都有可能有问题

    接口出参格式

    这里可参考Ant Design Pro的统一规范,这里截取一部分

    {
        "success": true,
        "data": {},
        "errorCode": "1001",
        "errorMessage": "error message",
        "showType": 2,
        "traceId": "someid",
        "host": "10.1.1.1"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    参考

    https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Status

    https://restfulapi.net/resource-naming/

    https://www.runoob.com/http/http-tutorial.html

    https://pro.ant.design/zh-CN/docs/request/#%E7%BB%9F%E4%B8%80%E8%A7%84%E8%8C%83

    https://www.zhihu.com/question/31363461

    https://www.zhihu.com/question/513865370

    https://www.zhihu.com/question/310737821

  • 相关阅读:
    【管理运筹学】第 9 章 | 网络计划(2,时间参数的计算 —— 工作时间的确定与事项的时间参数)
    TFT-LCD屏幕读取Flash芯片图片资源并显示
    Git 详细安装教程(详解 Git 安装过程的每一个步骤)
    ubuntu下ipynb文件转py文件
    【python】(十八)python常用第三方库——pymysql
    12 | 使用 Spark SQL执行CURL
    IDEA设置自动导入包
    数据结构之排序
    线程中的LockSapport于线程中断(一)
    session认证
  • 原文地址:https://blog.csdn.net/CrankZ/article/details/133908321