您的位置:首页 > 其它

RESTful服务最佳实践——(五)

2017-03-23 21:04 423 查看

HTTP动词

Http动词的主要遵循“统一接口”规则,并提供给我们对应于基于名词的资源的动作。最主要或者最常用的http动词(或者方法,正如它们被恰当地如此称呼)有POST、GET、PUT和DELETE。这些分别对应于创建、读取、更新和删除(CRUD)操作。也有许多其他的动词,但是使用频率比较低。对于使用较少的方法OPTIONS和HEAD使用得比其他动词更经常些。

GET

使用http的GET方法来检索(或者读)资源的表征。以“开心的”(或者正确的)方式(译者注:发出GET请求),GET方法会返回一个xml或者json格式的表征,以及一个http响应代码200(正确)。在错误情况下,它通常返回404(不存在)或400(错误的请求)。

例如:

GET http://www.example.com/customers/12345

GET http://www.example.com/customers/12345/orders

GET http://www.example.com/buckets/sample

据HTTP规范的设计,GET(以及HEAD)请求仅用于读取数据而不改变数据。因此,以这种方式使用时,它被认为是安全的。也就是说,他们可以被称为没有数据修改或污染的风险的–调用1次的效果如同调用10次,甚至根本没有调用过。此外,GET(和HEAD)是幂等的,这意味着使用多个相同的请求与使用单独的请求最终拥有的结果一致。

不要通过GET暴露不安全的操作–它永远不能修改服务器上的任何资源。

PUT

PUT经常被用于更新的功能。对一个已知的资源URI使用PUT,要求请求body中包含原始资源的最新更新的表征。

然而,在资源ID是由客服端而非服务端提供的情况下,PUT同样可以被用来创建资源。换句话说,如果PUT请求中URI包含不存在的资源ID值,则用于创建资源。并且,请求body中包含一个资源表征。许多人觉得这是令人费解和迷惑的。因此如果真的需要,这种创建方式也应该被谨慎使用。

另外,使用POST创建新的资源并在body表征中提供客户端定义的ID–应该是针对不含资源ID的URI(见以下POST的部分)。

例如:

PUT http://www.example.com/customers/12345

PUT http://www.example.com/customers/12345/orders/98765

PUT http://www.example.com/buckets/secret_stuff

成功更新,通过PUT请求返回200(或者不返回任何内容时是204)。如果使用PUT请求创建,成功创建返回Http状态码201。响应的内容是可选的–将消耗更多的带宽。创建时,没有必要通过头部的位置返回链接,因为客户端已经设置了资源ID。请参阅下面的返回值部分。

PUT不是一个安全操作,它在服务器上修改(或创建)状态,但它是幂等的。换句话说,如果你使用PUT创建或者更新资源并且使用相同的调用,资源仍然存在,且仍然有第一次调用后相同的状态。

例如,如果在资源增量计数器中调用PUT,这个调用方法就不再是幂等的。这种情况有时候会发生,且可能足以使其非幂等性记录在案。不过,建议保持PUT请求的幂等性。强烈建议非幂等性的请求使用POST。

POST

POST请求经常被用于创建新的资源,特别是它用于创建下属资源。下属资源也就是归属于其他资源(如父资源)的资源。换句话说,当创建一个新资源,POST请求发送给父资源和服务端,负责将新资源与父资源关联,并分配一个ID(新资源URL),等等。

例如:

POST http://www.example.com/customers

POST http://www.example.com/customers/12345/orders

成功创建,返回HTTP状态码201,返回一个位置头信息,其中带有指向最先创建的资源的链接。

POST请求既不安全又不是幂等,因此被定义为非幂等性资源请求。使用两个相同的POST请求很可能导致两个资源包含相同的信息。

PUT和POST的创建比较

简而言之,建议使用POST用于创建资源。否则,当客户端负责决定新资源具有哪些URI(通过它的资源名称或ID)时,使用PUT:如果客户知道结果URI(或资源ID)是什么,则对该URL使用PUT。否则,当服务器或服务端负责决定创建的资源的URI时使用POST。换句话说,当客户端在创建之前不知道(或无法知道)结果的URI时,使用POST创建新的资源。

DELETE

DELETE很容易理解。它是用来根据URI标识删除资源的。

例如:

DELETE http://www.example.com/customers/12345

DELETE http://www.example.com/customers/12345/orders

DELETE http://www.example.com/buckets/sample

成功删除,连同响应体返回http200(正确)状态码。响应体中可能还有删除项的表征(通常要求较多的带宽),或者封装的响应(参见下面的返回值)。换句话说,返回值可能是没有响应体、状态码204(无内容);或者JSON风格的响应体、推荐的状态码为200。

根据HTTP规范,DELETE操作是幂等的。如果你删除一个资源,资源旧被移除了。在资源上反复调用DELETE最终导致的结果相同:资源没了。如果调用DELETE用于计数器(用于资源),DETELE调用不再是幂等的。如前面所述,只要数据没有被更新,统计和测量的用法依然可被认为是幂等的。建议非幂等性的资源请求使用POST。

然而,这里有一个关于DELETE幂等性的警告。在一个资源上第二次调用DELETE往往会返回404(未找到)因为它已经移除了,因此不再是可找到的。这使得DELETE操作不再是幂等的。但如果资源不是被简单地标记为删除,而是被从数据库中删除,这种情况需要适当妥协。

结合主要HTTP方法和资源URI,总结出推荐的返回值,如下表:

http请求/用户/用户/{id}
GET200(正确),用户列表。使用分页、排序和过滤大导航列表。200(正确),单个用户。404(未找到),如果ID没有找到或ID无效。
PUT404(未找到),除非你想在整个集合中更新/替换每个资源。200(正确)或204(无内容)。404(未找到),如果没有找到ID或ID无效。
POST201(创建),带有链接到/客户/{id}的“位置”头部包含新的ID。404(未找到)
DELETE404(未找到),除非你想删除整个集合–通常是不可取的。200(OK)。404(未找到),如果没有找到ID或ID无效。
原文如下

HTTP Verbs

The HTTP verbs comprise a major portion of our “uniform interface” constraint and provide us the action counterpart to the noun-based resource. The primary or most-commonly-used HTTP verbs (or methods, as they are properly called) are POST, GET, PUT, and DELETE. These correspond to create, read, update, and delete (or CRUD) operations, respectively. There are a number of other verbs, too, but are utilized less frequently. Of those less-frequent methods, OPTIONS and HEAD are used more often than others.

GET

The HTTP GET method is used to retrieve (or read) a representation of a resource. In the “happy” (or non-error) path, GET returns a representation in XML or JSON and an HTTP response code of 200 (OK). In an error case, it most often returns a 404 (NOT FOUND) or 400 (BAD REQUEST).

Examples:

GET http://www.example.com/customers/12345

GET http://www.example.com/customers/12345/orders

GET http://www.example.com/buckets/sample

According to the design of the HTTP specification, GET (along with HEAD) requests are used only to read data and not change it. Therefore, when used this way, they are considered safe. That is, they can be called without risk of data modification or corruption—calling it once has the same effect as calling it 10 times, or none at all. Additionally, GET (and HEAD) is idempotent, which means that making multiple identical requests ends up having the same result as a single request.

Do not expose unsafe operations via GET—it should never modify any resources on the server.

PUT

PUT is most-often utilized for update capabilities, PUT-ing to a known resource URI with the request request body containing the newly-updated representation of the original resource.

However, PUT can also be used to create a resource in the case where the resource ID is chosen by the client instead of by the server. In other words, if the PUT is to a URI that contains the value of a nonexistent resource ID. Again, the request body contains a resource representation. Many feel this is convoluted and confusing. Consequently, this method of creation should be used sparingly, if at all.

Alternatively, use POST to create new resources and provide the client-defined ID in the body representation—presumably to a URI that doesn’t include the ID of the resource (see POST below).

Examples:

PUT http://www.example.com/customers/12345

PUT http://www.example.com/customers/12345/orders/98765

PUT http://www.example.com/buckets/secret_stuff

On successful update, return 200 (or 204 if not returning any content in the body) from a PUT. If using PUT for create, return HTTP status 201 on successful creation. A body in the response is optional-providing one consumes more bandwidth. It is not necessary to return a link via a Location header in the creation case since the client already set the resource ID. See the Return Values section below.

PUT is not a safe operation, in that it modifies (or creates) state on the server, but it is idempotent. In other words, if you create or update a resource using PUT and then make that same call again, the resource is still there and still has the same state as it did with the first call.

If, for instance, calling PUT on a resource increments a counter within the resource, the call is no longer idempotent. Sometimes that happens and it may be enough to document that the call is not idempotent. However, it’s recommended to keep PUT requests idempotent. It is strongly recommended to use POST for non-idempotent requests.

POST

The POST verb is most-often utilized for creation of new resources. In particular, it’s used to create subordinate resources. That is, subordinate to some other (e.g. parent) resource. In other words, when creating a new resource, POST to the parent and the service takes care of associating the new resource with the parent, assigning an ID (new resource URI), etc.

Examples:

POST http://www.example.com/customers

POST http://www.example.com/customers/12345/orders

On successful creation, return HTTP status 201, returning a Location header with a link to the newlycreated resource with the 201 HTTP status.

POST is neither safe or idempotent. It is therefore recommended for non-idempotent resource requests. Making two identical POST requests will most-likely result in two resources containing the same information.

PUT vs POST for Creation

In short, favor using POST for resource creation. Otherwise, use PUT when the client is in charge of deciding which URI (via it’s resource name or ID) the new resource will have: if the client knows what the resulting URI (or resource ID) will be, use PUT at that URI. Otherwise, use POST when the server or service is in charge of deciding the URI for the newly-created resource. In other words, when the client doesn’t (or shouldn’t) know what the resulting URI will be before creation, use POST to create the new resource.

DELETE

DELETE is pretty easy to understand. It is used to delete a resource identified by a URI.

Examples:

DELETE http://www.example.com/customers/12345

DELETE http://www.example.com/customers/12345/orders

DELETE http://www.example.com/buckets/sample

On successful deletion, return HTTP status 200 (OK) along with a response body, perhaps the representation of the deleted item (often demands too much bandwidth), or a wrapped response (see Return Values below). Either that or return HTTP status 204 (NO CONTENT) with no response body. In other words, a 204 status with no body, or the JSEND-style response and HTTP status 200 are the recommended responses.

HTTP-spec-wise, DELETE operations are idempotent. If you DELETE a resource, it’s removed. Repeatedly calling DELETE on that resource ends up the same: the resource is gone. If calling DELETE say, decrements a counter (within the resource), the DELETE call is no longer idempotent. As mentioned previously, usage statistics and measurements may be updated while still considering the service idempotent as long as no resource data is changed. Using POST for non-idempotent resource requests is recommended.

There is a caveat about DELETE idempotence, however. Calling DELETE on a resource a second time will often return a 404 (NOT FOUND) since it was already removed and therefore is no longer findable. This makes DELETE operations no longer idempotent, but is an appropriate compromise if resources are removed from the database instead of being simply marked as deleted.

Below is a table summarizing recommended return values of the primary HTTP methods in combination with the resource URIs:

HTTP Verb/customers/customers/{id}
GET200 (OK), list of customers. Use pagination, sorting and filtering to navigate big lists.200 (OK), single customer. 404 (Not Found), if ID not found or invalid.
PUT404 (Not Found), unless you want to update/replace every resource in the entire collection.200 (OK) or 204 (No Content). 404 (Not Found), if ID not found or invalid.
POST201 (Created), ‘Location’ header with link to /customers/{id} containing new ID.404 (Not Found).
DELETE404 (Not Found), unless you want to delete the whole collection—not often desirable.200 (OK). 404 (Not Found), if ID not found or invalid.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: