Python中文网

一个关于 编程问题的解答网站.

有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

rest HTTP中POST和PUT的区别是什么?

根据RFC 2616, § 9.5POST用于创建资源:

The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line.

根据RFC 2616, § 9.6PUT用于创建或替换资源:

The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI.

那么应该使用哪个HTTP方法来创建资源呢?或者两者都应该得到支持


共 (6) 个答案

  1. # 1 楼答案

    我想补充我的“务实”建议。当您知道可以检索要保存的对象的“id”时,请使用PUT。如果您需要(比如)返回一个数据库生成的id,以便将来进行查找或更新,那么使用PUT将不会太好

    因此:要保存现有用户,或客户端生成id并已验证id唯一的用户,请执行以下操作:

    PUT /user/12345 HTTP/1.1  <-- create the user providing the id 12345
    Host: mydomain.com
    
    GET /user/12345 HTTP/1.1  <-- return that user
    Host: mydomain.com
    

    否则,使用POST最初创建对象,并使用PUT更新对象:

    POST /user HTTP/1.1   <--- create the user, server returns 12345
    Host: mydomain.com
    
    PUT /user/12345 HTTP/1.1  <--- update the user
    Host: mydomain.com
    
  2. # 2 楼答案

    • 发布到URL服务器定义的URL上创建子资源
    • 放入URL客户端定义的URL中创建/替换整个资源
    • 补丁到URL更新该客户端定义的URL上资源的部分

    PUT和POST的相关规范为RFC 2616 §9.5ff.

    POST创建一个子资源,因此POST to /items将创建一个位于/items资源下的资源。 例如/items/1。两次发送相同的post数据包将创建两个资源

    PUT用于在客户端已知的URL上创建或替换资源

    因此:PUT只是创建的候选项,其中客户端在创建资源之前已经知道url。例如/blogs/nigel/entry/when_to_use_post_vs_put作为标题用作资源键

    PUT替换已知url上已存在的资源,因此两次发送同一请求无效。换句话说,对PUT的调用是幂等的

    RFC的内容如下:

    The fundamental difference between the POST and PUT requests is reflected in the different meaning of the Request-URI. The URI in a POST request identifies the resource that will handle the enclosed entity. That resource might be a data-accepting process, a gateway to some other protocol, or a separate entity that accepts annotations. In contrast, the URI in a PUT request identifies the entity enclosed with the request -- the user agent knows what URI is intended and the server MUST NOT attempt to apply the request to some other resource. If the server desires that the request be applied to a different URI,

    注意:PUT主要用于更新资源(通过替换资源的整体),但最近出现了使用补丁更新现有资源的趋势,因为PUT指定它替换整个资源RFC 5789.

    2018年更新:有一种情况可以避免出售。见"REST without PUT"

    With “REST without PUT” technique, the idea is that consumers are forced to post new 'nounified' request resources. As discussed earlier, changing a customer’s mailing address is a POST to a new “ChangeOfAddress” resource, not a PUT of a “Customer” resource with a different mailing address field value.

    摘自REST API Design - Resource Modeling by Prakash Subramaniam of Thoughtworks

    这迫使API避免在多个客户端更新单个资源时出现状态转换问题,并与事件源和CQR更好地匹配。当工作以异步方式完成时,发布转换并等待其应用似乎是合适的

  3. # 3 楼答案

    你可以在网上找到这样的断言

    两者都不完全正确


    更好的方法是根据动作的idempotence在PUT和POST之间进行选择

    放置意味着放置一个资源-用一个不同的东西完全替换给定URL上可用的任何东西。根据定义,PUT是幂等的。你想做多少次就做多少次,结果都一样x=5是幂等的。您可以放置资源,无论它以前是否存在(例如,创建或更新)

    POST更新资源、添加辅助资源或引起更改。POST不是幂等的,正如x++不是幂等的一样


    通过这个参数,PUT用于在您知道要创建的对象的URL时创建。当您知道要创建的类别的“工厂”或经理的URL时,可以使用POST来创建

    因此:

    POST /expense-report
    

    或:

    PUT  /expense-report/10929
    
  4. # 4 楼答案

    总体:

    PUT和POST都可以用于创建

    你必须问,“你在做什么?”,来区分你应该使用什么。假设您正在设计一个用于提问的API。如果您想使用POST,那么您可以对一系列问题执行此操作。如果你想使用PUT,那么你会对一个特定的问题这样做

    太好了,两者都可以使用,那么在我的RESTful设计中应该使用哪一种:

    您不需要同时支持PUT和POST

    你用什么取决于你自己。但是请记住,根据您在请求中引用的对象,使用正确的方法

    一些考虑:

    • 您是显式命名您创建的URL对象,还是由服务器决定?如果你给它们命名,那么就用PUT。如果由服务器决定,则使用POST
    • PUT的定义是假定幂等性,所以如果将一个对象放置两次,它就不会有额外的效果。这是一个很好的属性,所以如果可能,我会使用PUT。只需确保PUT幂等性在服务器中得到了正确的实现
    • 您可以使用具有相同对象URL的PUT更新或创建资源
    • 使用POST,您可以同时收到两个请求,对URL进行修改,它们可能会更新对象的不同部分

    一个例子:

    作为another answer on SO regarding this的一部分,我写了以下内容:

    POST:

    Used to modify and update a resource

    POST /questions/<existing_question> HTTP/1.1
    Host: www.example.com/
    

    Note that the following is an error:

    POST /questions/<new_question> HTTP/1.1
    Host: www.example.com/
    

    If the URL is not yet created, you should not be using POST to create it while specifying the name. This should result in a 'resource not found' error because <new_question> does not exist yet. You should PUT the <new_question> resource on the server first.

    You could though do something like this to create a resources using POST:

    POST /questions HTTP/1.1
    Host: www.example.com/
    

    Note that in this case the resource name is not specified, the new objects URL path would be returned to you.

    PUT:

    Used to create a resource, or overwrite it. While you specify the resources new URL.

    For a new resource:

    PUT /questions/<new_question> HTTP/1.1
    Host: www.example.com/
    

    To overwrite an existing resource:

    PUT /questions/<existing_question> HTTP/1.1
    Host: www.example.com/
    

    此外,更简洁地说,RFC 7231 Section 4.3.4 PUT状态(强调添加)

    4.3.4. PUT

    The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.

  5. # 5 楼答案

    POST表示“创建新的”,如“这里是创建用户的输入,为我创建它”

    PUT表示“插入,如果已经存在则替换”,如“这是用户5的数据”

    你可以POST举例说明。com/users因为您还不知道用户的URL,所以希望服务器创建它

    你可以PUT举例说明。com/users/id,因为您要替换/创建一个特定的用户

    使用相同数据发布两次意味着创建两个具有不同ID的相同用户。使用相同的数据放置两次会创建第一个用户,并在第二次将其更新为相同的状态(无更改)。因为无论执行多少次PUT之后都会得到相同的状态,所以每次都被称为“同等有效”——幂等。这对于自动重试请求很有用。按下浏览器上的“后退”按钮时,不再显示“是否确实要重新发送”

    一般建议是在需要服务器控制资源的URL生成时使用POST。否则使用PUT。喜欢PUT胜过POST

  6. # 6 楼答案

    总结:

    创建:

    可通过以下方式使用PUT或POST执行:

    PUT

    Creates THE new resource with newResourceId as the identifier, under the /resources URI, or collection.

    PUT /resources/<newResourceId> HTTP/1.1 
    

    POST

    Creates A new resource under the /resources URI, or collection. Usually the identifier is returned by the server.

    POST /resources HTTP/1.1
    

    更新:

    只能通过以下方式使用PUT执行

    PUT

    Updates the resource with existingResourceId as the identifier, under the /resources URI, or collection.

    PUT /resources/<existingResourceId> HTTP/1.1
    

    说明:

    将REST和URI作为常规处理时,在左侧上有通用,在右侧上有特定泛型通常被称为集合,而更具体的项目可以被称为资源。请注意,资源可以包含集合

    Examples:

    <-- generic -- specific -->

    URI: website.com/users/john
    website.com  - whole site
    users        - collection of users
    john         - item of the collection, or a resource
    
    URI:website.com/users/john/posts/23
    website.com  - whole site
    users        - collection of users
    john         - item of the collection, or a resource
    posts        - collection of posts from john
    23           - post from john with identifier 23, also a resource
    

    当你使用POST时,你总是引用一个集合,所以无论何时你说:

    POST /users HTTP/1.1
    

    您正在向用户集合发布新用户

    如果您继续尝试以下内容:

    POST /users/john HTTP/1.1
    

    它会起作用,但从语义上讲,您是说您希望向用户集合下的john集合添加资源

    使用PUT后,您将引用资源或单个项目,可能位于集合中。所以当你说:

    PUT /users/john HTTP/1.1
    

    您正在告诉服务器更新,或者创建用户集合下的john资源

    规格:

    让我强调一下规范的一些重要部分:

    POST

    The POST method is used to request that the origin server accept the entity enclosed in the request as a new subordinate of the resource identified by the Request-URI in the Request-Line

    因此,在集合上创建一个新的资源

    放置

    The PUT method requests that the enclosed entity be stored under the supplied Request-URI. If the Request-URI refers to an already existing resource, the enclosed entity SHOULD be considered as a modified version of the one residing on the origin server. If the Request-URI does not point to an existing resource, and that URI is capable of being defined as a new resource by the requesting user agent, the origin server can create the resource with that URI."

    因此,根据资源的存在创建或更新

    参考: