您正确地指出,HTTP 协议中没有任何固有的内容可以强制执行方法/动词的幂等属性,例如PUT
and DELETE
。 HTTP,作为无状态协议,不保留用户提出的每个请求的信息或状态;每个请求都被视为独立的。
引用维基百科上的HTTP 方法的幂等属性(强调我的):
请注意,方法是否幂等不是由
协议或网络服务器。写一个网页是完全可以的
应用程序,其中(例如)数据库插入或其他
非幂等操作由 GET 或其他请求触发。忽略
然而,这一建议可能会导致不良后果,
如果用户代理认为重复相同的请求是安全的
事实并非如此。
所以,是的,有可能偏离传统的实现,并推出诸如不改变的 POST 实现、非幂等 PUT 等之类的东西,可能不会出现重大的、危及生命的技术问题。但您可能会冒着让使用您的 Web 服务的其他程序员感到不安的风险,因为他们认为您不知道自己在做什么。
这里有一个重要的引述RFC2616关于 HTTP 方法safe(强调我的):
实施者应该意识到软件代表用户
他们通过互联网进行互动,并且应该小心允许
用户了解他们可能采取的任何可能会产生影响的操作
对自己或他人有意想不到的意义。
特别是,习俗已经确定 GET 和
HEAD 方法不应该具有采取行动的意义
除了检索之外。这些方法应该被认为是“安全的”。
这允许用户代理代表其他方法,例如 POST、PUT
并以特殊方式删除,以便让用户知道的
正在请求执行可能不安全的操作。
当然,也无法保证服务器不会
执行 GET 请求时会产生副作用;在
事实上,一些动态资源认为这是一个功能。重要的
这里的区别是用户没有请求副作用,所以
因此不能对他们负责。
UPDATE: 正如所指出的Julian,RFC 2616 已被 RFC 7231 取代。这是相应的部分.
因此,当您将 Web 服务发布为PUT
方法,然后我提交一个如下所示的请求:
PUT /users/<new_id> HTTP/1.1
Host: example.com
我期望创建一个新的用户资源。同样,如果我的请求如下所示:
PUT /users/<existing_id> HTTP/1.1
Host: example.com
我预计相应的现有用户会被更新。如果我通过多次提交表单来重复相同的请求,请不要弹出警告对话框(因为我喜欢既定的约定)。
相反,作为 POST Web 服务的使用者,我期望收到如下请求:
POST /users/<existing_id> HTTP/1.1
Host: example.com
更新相应的现有用户,而请求如下所示:
POST /users/<new_id> HTTP/1.1
Host: example.com
因为 URL 尚不存在而引发错误。