美文网首页Amazing Archspring boot
小小建议——restful命名规则(附请求错误码)

小小建议——restful命名规则(附请求错误码)

作者: 小胖学编程 | 来源:发表于2019-04-13 13:04 被阅读27次

    上来一首打油诗:
    动词加名词,名词用复数。
    动词分五类,之间可覆盖。
    名词若多级,从属或平等。
    状态需明确,响应给连接。

    1. 什么叫做Restful

    简单来讲:Restful是一种框架的规范与约束原则,符合这种规范的架构都是RESTful架构

    1.1 RESTful是什么意思?

    REST是Representational State transfer (资源)表述性转移。本质上是通过表述完成资源的转移

    1.2 RESTful的结构?

    RESTful的核心思想就是:客户端发出的数据操作指令都是“动词+宾语”的结构。例如GET /articles这个命令,GET是动词,/articles是宾语。

    需要注意的是:根据HTTP规范,动词一律大写。

    动词通常来说,其实就是五种HTTP方法,对应CRUD操作。

    动词 操作
    GET 读取
    POST 新建
    PUT 更新
    PATCH 部分更新
    DELETE 删除

    作为设计基础,还是需要遵循几个原则的:

    1. 当标准合理的时候遵守标准。
    2. API应该对程序员友好,并且在浏览器地址容易输入。
    3. API应该简单,直观,容易使用的同时优雅。
    4. API应该具有足够的灵活性来支持上层ui。
    5. API设计权衡上述几个原则。
    • GET /tickets #获取ticket列表;
    • GET /tickets/12 #查看某个具体的ticket;
    • POST /tickets #新建一个ticket;
    • PUT /tickets/12 #更新ticket 12;
    • DELETE /tickets/12 #删除ticket 12;

    显然从API用户的角度来看,“资源”应该是一个名词。即使在内存数据结构模型和资源已经有了很好的对应,API设计的时候仍然不需要把它们一对一的暴露出来,这里的关键是隐藏内部资源,暴露必须的对外资源。

    2. 如何书写RESTful

    2.1 动词的覆盖

    有些客户端只能使用GETPOST这两种方法,服务器必须接受POST模拟其他三个方法(PUT/PATCH/DELETE)。

    这时,客户端发出的HTTP请求,需要加上X-HTTP-Method-Override属性,告诉服务器应该使用哪种动词,覆盖POST方法。

    POST /api/Person/4 HTTP/1.1  
    X-HTTP-Method-Override: PUT
    

    上面代码中,X-HTTP-Method-Override指定本次请求的方法是PUT,而不是POST。

    2.1 宾语必须是名词

    宾语就是API的URL,是Http动词作用的对象,他表述的是一个资源。应该是名词,不应该是动词。

    !!!Restful反例

    /getAllCars
    /createNewCar
    /deleteAllRedCars
    

    2.2 宾语是单数还是复数

    既然URL是名词,那么应该使用复数,还是单数?

    这里没有统一的规定,但是常见的操作是读取一个集合,比如GET /articles(读取所有的文章)这里明显是复数。

    为了统一起见,建议都使用复数URL,比如GET /articles/2要好于GET /article/2

    2.3 多级的URL的写法

    按照Rails中标准定义的方式:

    1. 若定义这个资源的两个参数具有从属关系,那么生成的url就是owner/1/property/1,其中property从属于owner。比如用户1的编号为2的文章,就是users/1/articles/2
    2. 如果两个资源是平等的,那么一般是作为URL中HTTP方法的参数。

    举个小栗子

    比如汇款动作,从账户1向账户2汇款500元。如何设计URL?
    小优同学:POST /accounts/1/transfer/500/to/2
    小胖老师:答错了,请坐下。
    正确的应该是:将动词转换为名称,(只是一个汇款操作)
    即:POST /accounts/transaction?from=1&to=2&amount=500.00

    3. 状态码

    客户端的每一次请求,服务器都必须给出回应。回应包括HTTP状态码和数据两部分。

    状态码 相关操作
    1xx 相关信息
    2xx 操作成功
    3xx 重定向
    4xx 客户端错误
    5xx 服务器错误

    这五大类共包含了100多种状态码,覆盖了绝大部分可能的情况。每一种状态码都有标准(或者是约定)解释,客户端只需要查看状态码,就可以判断出发生了什么情况,所以服务器应返回尽可能精确的1状态码。

    API不需要1xx状态码,下面介绍其他四类状态码的精确含义。

    3.1 2xx状态码

    虽然200状态码表示操作成功,但是不同的方法可以返回更精确的状态码。

    HTTP操作 状态码
    GET 200 ok
    POST 201 created
    PUT 200 ok
    PATCH 200 ok
    DELETE 204 no content
    • POST返回201状态码,表示生成了新的资源;

    • DELETE返回204状态码,表示资源已经不存在;

    • 202 Accepted状态码表示服务器已经收到请求,但还未进行处理,会在未来再处理,通常用于异步操作。

    HTTP/1.1 202 Accepted
    
    {
      "task": {
        "href": "/api/company/job-management/jobs/2130040",
        "id": "2130040"
      }
    }
    

    3.2 3xx状态码

    API用不到301状态码(永久重定向)和302状态码(暂时重定向,307也是这个含义),因为它们可由应用级别返回,浏览器会直接跳转,API级别可以不考虑这两种情况。

    API用到的3xx状态码,主要是303 See Other,表示参考另一个URL。它与302和307含义一样,也是“暂时重定向”,区别在于302和307用于GET请求,而303用于POST、PUT和DELETE请求。收到303以后,浏览器不会自动跳转,会让用户自己决定下一步怎么办,下面是一个例子。

    HTTP/1.1 303 See Other
    Location: /api/orders/12345
    

    3.3 4xx状态码

    4xx状态码表示客户端错误,主要有下面几种。

    状态码 含义
    400 Bad Request 服务器不理解客户端请求,未做任何处理
    401 Unauthorized 用户未提供身份验证凭证,或者没有通过身份验证
    403 Forbidden 用户通过身份验证,但没有权限访问请求资源
    404 Not Found 所请求资源不存在,或不可用
    405 Method Not Allowed 用户已经通过身份验证,但是所用HTTP方法不在权限内
    410 Gone 所请求资源已经从这个地址转移,不可再用
    415 Unsupported Media Type 客户端要求返回格式不支持。比如API只能返回JSON,但Client要求返回XML
    422 Unprocessable Entity 客户端上传附件无法处理,导致请求失败
    429 Too Many Request 客户端的请求次数超过限额

    3.4 5xx状态码

    5xx状态码表示服务端错误,一般来说,API不会像用户透露服务器的详细信息,所以只要两个状态码就够了。

    状态码 含义
    500 Internal Server Error 客户端请求有效,服务器处理时发生了意外
    503 Service Unavailable 客户端无法处理请求,一般用于网站维护状态

    4. 服务器回应

    4.1 不要返回纯文本

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

    客户端请求时,也要明确告诉服务器,可以接受JSON格式,即请求的HTTP头的ACCEPT属性也要设为application/json

    GET /orders/2 HTTP/1.1 
    Accept: application/json
    

    4.2 发生错误时,不要返回200错误码

    有一种不恰当的做法是,即使发生错误,也返回200状态码,把错误信息放在数据体里面,就像下面这种:

    HTTP/1.1 200 OK
    Content-Type: application/json
    
    {
      "status": "failure",
      "data": {
        "error": "Expected at least two items in list."
      }
    }
    

    上面代码,解析数据体以后,才能得知操作失败。
    这种做法实际上是取消了状态码,这是完全不可取的。正确的做法是:状态码反映发生的错误,具体的错误信息放在数据体里面返回。

    HTTP/1.1 400 Bad Request
    Content-Type: application/json
    
    {
      "error": "Invalid payoad.",
      "detail": {
         "surname": "This field is required."
      }
    }
    

    4.3 提供链接

    HATEOAS怎么读(Hypermedia as the engine of application state)超媒体作为应用状态引擎。【“小胖哥哥,你英语翻译太棒了”——小优】

    我们知道REST是使用标准的HTTP方法来操作资源的。但仅仅因此就理解成带CURD的WEB数据库架构就太low了吧。这种说法忽略了一个核心的概念,即“超媒体即应用状态引擎(Hypermedia as the engine of application state)”。

    超媒体是什么?

    当你浏览Web页面的时候,从一个连接跳到一个页面,再从另一个连接跳到另外一个页面,就是利用超媒体的概念:把一个个资源链接起来。

    要达到这个目的,就要求在表述表格里面加入链接来引导客户端,在《RESTFul Web Services》一书中,作者把这种具有链接的特性称为“连通性”

    RESTful API最好做到HATEOAS,即返回结果中提供链接,连向其他API方法,使得用户不用查询文档,也知道下一步怎么做。比如,用户向api.example.com的根路径发出请求,会得到这样一个文档。

    {"link": {
      "rel":   "collection https://www.example.com/zoos",
      "href":  "https://api.example.com/zoos",
      "title": "List of zoos",
      "type":  "application/vnd.yourformat+json"
    }}
    

    上面代码表示,文档中有一个link属性,用户读取这个属性就知道下一步调用什么API,rel表示这个API与当前网址的关系(collection关系,并给出该collection的网址),href表示API的路径,title表示API的标题,type表示返回类型。

    Hypermedia API的设计被称为HATEOAS。GIThub的API就是这种设计,访问api.github.com就会得到一个所有可用API的网址列表。

    HATEOAS实践

    那我们就去访问访问https://api.github.com/user这个地址吧。

    访问api.github.com/user

    参考文章:
    restful 接口命名规则

    RESTful API 最佳实践

    不要被名字吓到-RESTful、HATEOAS、Spring boot之整合

    相关文章

      网友评论

        本文标题:小小建议——restful命名规则(附请求错误码)

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