zoukankan      html  css  js  c++  java
  • RESTful设计中的常见疑问

    最近写了几个有关RESTful的API相关内容,也谈谈对常见问题的自己的理解。

    1.什么是RESTful

    详情可以看http://www.ruanyifeng.com/blog/2011/09/restful.html

    简单可以这么理解,使用URI去代表资源,使用HTTP VERB(GET PUT等)对资源的操作。

    2.为什么要用RESTful

    使用RESTful,优点有很多,也方便不同的请求方去请求数据。列举两个:

    • HTTP方法语义都很明确,使用GET去获得数据,使用DELETE去删除数据。
    • 返回值也是很明确的HTTP RESPONSE,200就是执行成功,400就是请求错误。

    那是不是每一个API都需要使用REST风格呢?我觉得不是,这要看团队、项目而定,不必一味强求。

    3.在URI资源地址中使用v1之类的版本号符不符合RESTful?

    这个涉及到RESTful的版本管理,常见的方法有这么几种。

    URL Path

    /api/v1/helloworld
    

    很多公开的API地址里面,都带有version信息,如果非要去扣符不符合RESTful,估计要吵起来。但是这个方式很便捷、明确,调用方一看就明白,也没有额外的工作量去做。不过缺点也很明显,由于已经限定死了版本号在URI中,无法实现同一个URI地址版本的灵活切换,也不能指定默认版本。

    Query String

    /api/helloworld?api-version=1.0
    

    这个方式没有改变URI本身,但是需要调用方去额外处理Query string,不过好在这个可以指定默认的。

    Media Types

    POST api/helloworld HTTP/1.1
    host: localhost
    content-type: text/plain;v=2.0
    content-length: 12
    
    Hello there!
    

    在Content-Type里面添加v=x.x的版本号也是一个不错的选择,可以实现QueryString类似的功能。

    有一些现成的库可以帮助我们实现上面的Versioning方法,常见的是aspnet-api-versioning

    4.什么是安全性?

    无论请求多少次,服务器的状态(资源)都不会改变,那么这个方法就是安全的。

    GET HEAD都应该设计成安全的。

    5.什么是幂等性?

    无论对资源操作多少次,服务器资源结果总是一样的,那么这个方法就是幂等的。注意这里的说法,是服务器的资源结果是一样的,不代表请求的返回结果是一样的。比如DELETE请求,它是幂等的,但是删除一个资源很多次的情况(多次执行DELETE api/student/1,第一次返回成功,第二次返回失败,但是不影响服务器上对应的记录已经删除的状态。

    GET、HEAD、PUT和DELETE请求都应该设计成是幂等的。

    6.新增数据用POST还是PUT?

    资源新增可以用POST也可以用PUT,但是设计上有几个区别。

    幂等性

    PUT是幂等的,POST不是,如果设计上需要不应用幂等性,那么使用POST。比如POST计数器的应用,每次POST,计数器都增长1。

    请求目标

    POST一般请求的是资源集合,而PUT一般请求是一个具体的资源。

    PUT /students/{id}
    POST /students
    

    这也意味着,语义上,POST是请求在集合中新增资源。

    主动权

    • 如果id不是由调用方生成的情况下,需要指定的资源ID的PUT方法就不好实现了。这种情况,使用POST到资源更合理,主动权在服务器方,服务器创建资源之后,返回201携带新生成的对象URI。
    • 如果id是由调用方生成的情况下(比如一些硬件设备产生的数据),使用POST和PUT都可以,但是PUT有幂等性,显得更加明确,这种时候我一般选择使用PUT。

    覆盖

    PUT语义是要求覆盖的,如果数据已经存在,就必须覆盖。POST的没有这个要求,可以有别的行为。

    7.修改数据应该使用PUT还是PATCH?

    不一定,要看情况。PUT是覆盖性的修改,而PATCH是追加性的修改。

    • 使用PUT的时候,需要将数据完整返回,如果有的字段没有赋值,那么将保持为默认值。
    • PUT是幂等的,PATCH不是,因此多次执行PUT请求,结果是一样的;执行PATCH有可能不一样。
    {
    "value": 
        {
            "id": "235314",
            "deviceId": "123",
            "type": "低温"
        }
    }
    

    如果发送的数据只含有deviceId,执行PUT之后,资源变成:

    {
    "value": 
        {
            "id": "235314",
            "deviceId": "111"
        }
    }
    

    执行PATCH,资源变成:

    {
    "value": 
        {
            "id": "235314",
            "deviceId": "111",
            "type": "低温"
        }
    }
    

    8.没有数据返回204还是404?

    问题:

    如果请求一个这样的资源

    GET api/sutudents/homework
    

    在没有homework的情况下应该返回HTTP 204 NoContent还是返回HTTP 404 NotFound?

    乍看一眼,觉得好像都差不多,没内容和没找到反正都是没有。但深入想想,还是有很大的区别的。

    1. 404返回的更倾向于表述不存在的性质,而204返回表述没有内容,也就是存在,但是没有内容。
    2. 4xx返回表述大体是请求有问题,而2xx返回表述大体是请求没有问题。

    所以,对于上面的问题,这么理解,如果homework是已经创建的资源,但是内容为空,那么返回204是可以的,但是如果homework这个东西就不存在,那么应该返回404。

    个人认为直接返回200,携带对应的空内容会比204要对调用方更加友好,至少和有数据的情况是一样处理。

    9.写给前端

    有很多前端同学需要服务器返回固定的成功信息(比如200)或者错误信息(比如400)。但HTTP CODE很多,一个一个判断效率很低,好在HTTP CODE是分类的,比如2xx大体是OK的,4xx都是有问题的。可以通过CODE / 100 == 2之类的方法去大体确定返回的状态 。

  • 相关阅读:
    poj 1579(动态规划初探之记忆化搜索)
    hdu 1133(卡特兰数变形)
    CodeForces 625A Guest From the Past
    CodeForces 625D Finals in arithmetic
    CDOJ 1268 Open the lightings
    HDU 4008 Parent and son
    HDU 4044 GeoDefense
    HDU 4169 UVALive 5741 Wealthy Family
    HDU 3452 Bonsai
    HDU 3586 Information Disturbing
  • 原文地址:https://www.cnblogs.com/podolski/p/12895611.html
Copyright © 2011-2022 走看看