html表单method属性仅支持get和post,put/delete会被静默降级为get;需用javascript拦截提交并fetch发送,或后端通过_method字段模拟rest方法。

form method="put" 或 delete 会被静默降级为 get
浏览器根本不会发 PUT 或 DELETE 请求——method 属性只认 get 和 post,其他值(包括 PUT、Delete、delete)全部被忽略或降级为 GET。你在 Network 面板里看到的 Request Method 永远是 GET,后端连请求都收不到,更别说 405 错误了。
这不是兼容性问题,而是 HTML 规范强制限定:<form></form> 的 method 只允许两个合法值。大小写不敏感(POST、Get 都行),但拼错或用 RESTful 方法名就是无效。
-
formmethod="put"同样无效,它只支持get/post,不是“局部放开” - 旧版 IE 可能直接忽略整个
formmethod属性,退回到<form></form>的默认 method - 别信“加个 meta 或 doctype 就能启用”,HTML 标准没留这个口子
想发 PUT/DELETE?必须用 JavaScript 拦截原生提交
原生表单走不通,就得绕开它。核心思路是:阻止默认提交行为,用 fetch() 或 XMLHttpRequest 手动构造请求。
关键点:
- 给
<button type="submit"></button>绑定click或给<form></form>绑定submit事件,调用event.preventDefault() -
fetch()的method选项可自由设为"PUT"或"DELETE",不受 HTML 限制 - 如果后端需要 CSRF token,得从 hidden input 或 meta tag 里手动读取并塞进
headers
示例(简洁版):
form.addEventListener('submit', async e => {
e.preventDefault();
const data = new FormData(form);
await fetch('/api/user/123', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(Object.fromEntries(data))
});
});
后端配合方案:Spring Boot / Django 等框架的 _method 伪造模式
如果你没法改前端逻辑(比如遗留系统或 CMS 表单),后端可以妥协:接受 POST 请求,但通过隐藏字段识别真实意图。
这依赖框架提供的过滤器或中间件,不是浏览器行为:
- Spring Boot 需启用
spring.mvc.hiddenmethod.filter.enabled=true,并确保HiddenHttpMethodFilter生效 - 表单保持
method="post",但加一个<input name="_method" value="delete"> - Django 默认支持
_method,Flask 需用扩展如flask-methodoverride - 注意:CSRF token 必须存在且校验通过(尤其 Spring Security 启用时)
这种方案本质是“语义欺骗”,实际网络层仍是 POST,只是后端路由做了映射。别把它当成真正的 HTTP 方法切换。
容易被忽略的坑:代理、CDN 和中间件会吃掉 _method
即使后端开了 HiddenHttpMethodFilter,请求也可能在半路失效。
常见断点:
- Nginx 或 CDN 默认不转发
_method字段(尤其当它出现在 query string 而非 body 时) - 某些 WAF 或安全网关会清洗 body 中的非常规字段,
_method被静默丢弃 - 如果表单用
enctype="multipart/form-data",部分老版本 Spring 无法正确解析_method - 前端用
fetch()发 PUT/DELETE 时,若没带Credentials或Content-Type,可能触发预检(OPTIONS),而预检失败会导致整个请求卡住
真要稳定用 RESTful 方法,优先走 JS + fetch;用 _method 是权宜之计,得全程盯住中间链路。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











