您正确地指出,HTTP 协议中没有任何内在的东西可以强制方法/动词(如PUT
和)的幂等属性DELETE
。HTTP 是一种无状态协议,不保留用户发出的每个请求的信息或状态;每个请求都被视为独立的。
引用维基百科关于HTTP 方法的幂等属性(强调我的):
请注意,协议或 Web 服务器不强制执行方法是否具有幂等性。完全可以编写一个 Web 应用程序,其中(例如)数据库插入或其他非幂等操作由 GET 或其他请求触发。但是,如果用户代理认为重复相同的请求是安全的,而实际上并非如此,那么忽略此建议可能会导致不良后果。
所以是的,有可能偏离传统的实现,并推出诸如不改变的 POST 实现、非幂等 PUT 等可能没有重大的、危及生命的技术问题。但是您可能会冒着惹恼其他使用您的 Web 服务的程序员的风险,认为您不知道自己在做什么。
这是RFC2616中关于安全的 HTTP 方法的重要引用(强调我的):
实施者应该意识到该软件代表了用户在互联网上的交互,并且应该小心让用户意识到他们可能采取的任何可能对他们自己或他人产生意想不到的意义的行动。
特别是,已经建立了约定,即 GET 和 HEAD 方法不应该具有采取除检索之外的操作的意义。这些方法应该被认为是“安全的”。这允许用户代理以特殊的方式表示其他方法,例如 POST、PUT 和 DELETE,以便用户意识到正在请求可能不安全的操作。
当然,不可能确保服务器不会因为执行 GET 请求而产生副作用;事实上,一些动态资源认为这是一个特性。这里的重要区别是用户没有请求副作用,因此不能对它们负责。
更新:正如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 尚不存在。