0

我有一个这样的网址:

http://www.example.com/users/

我想用 PUT 请求创建一个新用户:

requests.put('http://www.example.com/users/john/', data={'password': 1234})

实际上,此请求创建了一个新的用户资源并返回 201“已创建”状态代码,如果我想更新该资源,我可以发出如下请求:

requests.put('http://www.example.com/users/john/', data={'username': 'jane'})

好吧,我可以在 Location 标头中返回带有 301“永久移动”状态代码和新创建的 url 的响应。当我试图在控制器代码中实现这样的逻辑时,问题就出现了,在逻辑的某些部分,我有一些代码可以检查用户名是否存在,例如:

if username in users:
  # do something

如果我使用 PUT 创建一个新资源,在这种情况下,一个用户说用户名已经存在,我可以返回一个 409“冲突”状态代码,如果用户名不存在,则返回一个消息,如“用户名已经存在,选择另一个” '不存在我只是返回一个 201“创建”,逻辑上这个创建操作不需要身份验证原因就像一个“注册”操作。

另一方面,当我请求更新资源时,我需要进行某种身份验证以允许用户更新他的帐户信息。

因此,如果我使用用户名变量来确定我必须执行的操作,并且用户名名称已经存在,我不知道何时需要验证或无效的用户名响应来响应。

我的第一个想法是使用 POST 请求来创建新用户并 PUT 仅用于更新行为,但似乎使用 POST 来创建标识符不是由服务器创建的资源是一个坏主意。

所以我的问题是,是否有任何方法可以通过 PUT 请求实现创建和更新功能?

4

1 回答 1

1

对于更新,另一个选项是 PATCH,您可以验证该请求并将其视为纯更新。

当您创建一个对象时,您可以针对集合创建它并返回 201。当您完全替换整个资源时,您可以针对用户资源进行 PUT。PATCH 可能用于部分更新。

Create (Anonymous)
Request  : [POST|PUT]  /users/        body=full object (incuding name)
Response : 201 LOCATION =  /users/123

Overwrite (Auth)
Request   : [PUT]      /users/123     body=full object - id implies overwrite    
Response  : 200

Update (Auth)
Request   : [PATCH]    /users/123     body=partial objects      
Response  : 200

通过针对父资源(在本例中为用户集合)创建资源(通过 POST | PUT)。它解决了这个问题。这也是一种很好的做法。您还应该使用永久链接(int id 或 guid)创建资源,以便用户可以更改他们的名称并且不会让存储的引用中断。

如果您希望标识符成为永久链接并且您希望它由客户端创建(如评论中所建议的那样),那么您需要为标识符使用类似 guid 的东西。

于 2013-03-04T22:57:36.760 回答