HTTP的DELET方法能不能有Body?

起因

长期以来,我基本上从事的都是移动端开发,对后台的API规范属于一知半解了,倒是以前研究过GET方法能不能有BODY,但从没想过HTTP的DELETE方法能不能有Body,毕竟我很少有用到DELETE,以至于我一直觉得DELETE支持BODY,直接到今天Calude给我上了一课,起因是我想写一个删除账号的API,要带上一个验证码,如果从RESTful规范和语义上说,用DELETE显然是更适合的,但Claude Code却建议我使用POST:

go 复制代码
1.  **`POST` 还是 `DELETE` 方法**:语义上"删除"更该用 HTTP `DELETE`,但 `DELETE` 带 body 在部分客户端/网关上支持不一致,而且现有 `signup`/`reset-password` 都是状态变更但用的 `POST`。为了跟现有风格一致、也避免 body-in-DELETE 的坑,**建议沿用 `POST`**。

也就是说DELETE方法在不同的地方对BODY的支持是不一致的,有的是支持的,有的是不支持。本着对真相的渴望,我又去问了Gemini,Gemini告诉我:"技术上可以,但极度不推荐 。根据 MDN Web Docs 的定义,HTTP 规范对DELETE 请求的 Body 没有定义明确的语义。这意味着标准允许请求带有 Body,但服务器在接收到带有 Body 的 DELETE 请求时,可以根据自身的实现自由处理(例如忽略它或直接处理)"。也就是说,你可以给DELTE加一个。而且大多数web服务器也不会明确禁止这样做。就像大多数web服务器也不会禁止GET请求带body一样。这更多的是服务端的endpoint handler和客户端使用服务的实现细节。

事实上真是这样的吗?

如果我们去查阅HTTP 协议的官方规范(RFC 9110),你会发现DELETE还真就不应该带BODY,规范原文如下:

markdown 复制代码
A client **SHOULD NOT** generate content in a DELETE request unless it is made directly to an origin server that has previously indicated, in or out of band, that such a request has a purpose and will be adequately supported. An origin server SHOULD NOT rely on private agreements to receive content, since participants in HTTP communication are often unaware of intermediaries along the request chain.

翻译一下:

markdown 复制代码
客户端**不应当**在 DELETE 请求中生成正文内容,除非该请求是直接发送给源服务器,且该服务器此前已通过带内或带外方式明确表明此类请求具有特定目的且会得到充分支持。源服务器**不应当**依赖私下协议来接收正文内容,因为 HTTP 通信的参与者通常无法察觉请求链中存在的中间件(如代理服务器等)。

SHOULD NOT本身不是禁止的意思,也就是说上面说的"技术上可以实现,但不推荐"系列。而规范中说到的豁免情况也就不难理解了,每个HTTP的具体实现都规范的遵循程序都不一致,比如说早期的Flutter DIO就支持DELETE带BODY,后来DIO为了遵循HTTP规范,又取消DELETE带BODY的支持,而早期JDK也是不支持的,CURL本身应该是支持,所以如果你能直接把请求直接发送给源服务器,且该服务器此前已通过带内(in-band)或带外(out-of-band)方式明确表明此类请求具有特定目的且会得到充分支持的情况下,你就可以使用带BODY的DELETE了。

其实从http报文的角度看,他们完全都是一样的。没有任何区别。大家能发送的信息都是一样的。你能做的我也能做,不一样的在于method所代表的这个请求的语义。

结论

说到底,在http规范任何方法都能发送请求实体。他们报文时,没有任何区别的;但是在浏览器中,比如说,XMLHttpRequest就遵循规范的限制,浏览器中ajax发送的http请求GETDELETE请求不能携带实体。

相关推荐
benbenAItalk3 小时前
数字人口播视频的批量生产实践:素材规范、任务编排与质量验收
java·前端·音视频
2601_962885724 小时前
如何用 Python 扫描 A 股跳空缺口并统计缺口回补概率?
java·前端·python
西瓜太郎12344 小时前
Claude Code、Codex CLI、Gemini CLI 能否共用一枚 Key?先看协议选择矩阵
前端·api 网关·claude code·gemini cli·codex cli
陈随易6 小时前
在Finch用了62亿词元,我认为这是新一代Agent工具之神
前端·人工智能·后端
水域安全老周6 小时前
水趣钓鱼救生衣专利拆解:两级锁紧如何解决落水人衣分离
java·前端·网络
计算机魔术师7 小时前
Anthropic CEO突然喊踩刹车,OpenAI罕见力挺:AI这辆车不能只踩油门了
前端
wing987 小时前
从codex转战workbuddy使用一周的感受
前端·人工智能·后端
EatFan7 小时前
Java接入支付宝 JSAPI 支付保姆教程(二):流程讲解与前后端代码讲解
前端·spring boot·后端·微信小程序·小程序·uni-app
梦想平凡8 小时前
百游棋牌源代码开发搭建教程(五):房间创建、座位分配与请求幂等实现
前端·javascript·数据库·源代码管理
IT_陈寒8 小时前
Redis的Set操作居然能把我的服务整挂了?
前端·人工智能·后端