美文网首页程序员java进阶干货
谈谈如何设计RESTful API

谈谈如何设计RESTful API

作者: 简xiaoyao | 来源:发表于2017-10-29 21:29 被阅读305次

REST是一种架构风格,由Roy Thomas Fielding在他2000年的博士论文中提出,由于其简洁高效的设计,越来越多的网络服务开始采用REST风格设计和实现;本文主要根据业界已经总结出来的RESTful API的设计原则,并结合我工作中的API设计经验,总结出一套我认为最合适的设计准则

API(应用编程接口)大家都很熟悉,一套API的设计一般遵循以下步骤:

  • 接口应用场景是什么
  • 如何定义接口
  • 其它注意点

对于接口应用场景我想不需要做过多阐述,既然是REST,基本就是网络应用场景了,本文将就后面两步进行详细阐述

1. 如何定义接口

  • Root URL尽量简洁
    简洁总是好的,不要将API的Root URL设计得过于复杂,这样既没有必要,同时也会难以维护,API一般应该作为一个单独的服务向外提供,复杂的Root URL可能意味着你的系统拓扑有问题,所以尽量以简单明了的形式呈现Root URL:

    https://example.org/api/
    https://api.example.com/
    
  • API上需标明版本
    如果你能预见该API后期不会有迭代增长(基本不可能),那么可以不需要版本信息;否则带上版本信息,它能让后续扩展更加容易,同时也能保持前向兼容,版本信息也以简洁为主,如:

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

    也有人建议将版本放置于header中,我个人认为放在header中没有放在API URL根部好

  • 资源的操作采用名词形式
    每个资源使用两个URL,资源集合用一个URL,具体某个资源用一个URL,如:

    /employees         #资源集合的URL
    /employees/56      #具体某个资源的URL
    
  • 非资源操作使用动词
    有时API调用并不涉及资源(如计算,翻译或转换)。例:

    GET /translate?from=de_DE&to=en_US&text=Hallo
    

    在这种情况下,API不会返回任何资源数据。而是执行一个操作并将结果返回给客户端。因此,你应该在URL中使用动词而不是名词,来清楚的区分资源请求和非资源请求

  • 表述资源的名词采用复数形式
    名词采用复数形式更多的是一种个人爱好,但复数形式在大部分情况下确实更加合理,如果一定要使用单数形式也可以,但需要注意的是不要同一个资源单复数混用,如:

    /animals   # 复数
    /animal/36    # 单数
    

    这样看起来很混乱,且容易出错

  • 使用HTTP action表达资源操作,而不要通过 动词+资源名词 表达
    什么意思呢?比如下面的API示例:

    /getAllEmployees
    /getAllExternalEmployees
    /createEmployee
    /updateEmployee
    

    它将对资源的操作表达成一个动词+资源名词形式的短语,这种形式的主要缺点在于API看起来比较凌乱,且每个资源对应的URL数目会较多,对比看更好的设计:

    GET /employees
    GET /employees?state=external
    POST /employees
    PUT /employees/56
    

    每个资源对应一个URL,通过HTTP action和HTTP参数来表述对资源的操作,形式统一,URL精简;具体 HTTP action与操作对应关系见下表:

    URL POST(创建) GET(读取) PUT(提供整体信息) PATCH (提供局部信息) DELETE(删除)
    /employees 创建一个新员工 列出所有员工 批量更新员工信息 批量更新员工信息 删除所有员工
    /employees/56 error 获取56号员工的信息 更新56号员工的信息 更新56号员工的信息 删除56号员工

    另外还有两种并不常用的HTTP action

    HEAD OPTIONS
    返回资源的元数据,如资源的hash值,资源的更新时间等 返回允许客户端对该资源进行哪些操作
  • 使用HTTP 响应状态码对结果进行分类
    作为HTTP应用,使用HTTP响应状态码对结果进行分类不但符合通用的标准,还会带来很多其他好处,如一些负载均衡服务器就会自动减少对某些过多50X错误的服务器发送调用请求,常用的响应状态码有:

    2xx:成功 3xx:重定向 4xx:客户端错误 5xx:服务器错误
    200 成功 301 永久重定向 400 错误请求 500 内部服务器错误
    201 创建 304 资源未修改 401未授权 。。。
    。。。 。。。 403 禁止 。。。
    。。。 。。。 404 未找到 。。。
  • 返回有用的错误提示
    除了合适的响应状态码之外,还应该在HTTP响应正文中提供有用的错误提示和详细的描述。让调用方更方便的定位问题,如请求:

    GET /employees?state=super
    

    对应响应:

    // 400 Bad Request
    {
        "message": "您的请求参数status不符合要求,它必须是正整数",
        ...
    }
    
  • 其他参数采用查询参数形式(api?param=xxx)而非路径参数形式(api/xxx
    所谓其他参数指的是指不在REST规则里的参数,如过滤,搜寻,分页等,请求实例:

    /employees?offset=30&limit=15
    
  • 根据使用场景决定返回格式类型
    返回格式分为两种:

    • 数据格式,如json,xml等;当前大部分情况下都使用json,若非特殊考虑也是推荐使用json,它相较于xml更易读,且数据量更小
    • 命名格式,如小驼峰命名法(returnData),下划线命名法(return_data)等;命名格式一般需要根据客户端进行决定,比如调用的客户端基本都是WEB前端,那么使用小驼峰命名法会更好,以与JS兼容

其它注意点

  • 安全第一
    任何一个API,即便是内部API依然要考虑安全校验,如调用者身份验证,请求数据量是否超过阈值等
  • API文档很重要
    实际中的API很少会100%遵循本文的原则,这样的API照样可以正常工作,但是如果你的API没有一份清晰易懂且及时更新的文档,那么对于大部分调用者来说,这就是烂API,好的文档能让调用者清楚的知道API的作用,同时为API提供者省去很多不必要的维护工作
  • 跟踪所有API的调用情况,对使用频繁的API进行重点优化
    这一点没有那么绝对,对于内部API接口,可以不需要;但是对于开放API接口,如果能针对调用频繁的API进行单独优化,那么就可以提升使用API体验
  • 快过期的API也需要维护
    对于快过期的API需要在文档提前声明,特定时间点哪些API将不再维护,同时返回404 not found或301重定向至当前可用的API

相关文章

网友评论

    本文标题:谈谈如何设计RESTful API

    本文链接:https://www.haomeiwen.com/subject/abvlextx.html