Rails项目中Axios发送/post的POST请求出现路由匹配错误
问题根因
1. 根本没有发出Axios的POST请求
服务端日志已经明确说明收到的是GET请求,而非Axios声明的POST请求,从特征就能判断来源:
- Axios的
post方法默认会把传入的参数作为JSON请求体发送,不会把参数拼到URL的查询字符串里 - 日志中请求URL携带
title/text/pseudo等表单字段的查询参数,且空格被编码为加号,完全符合浏览器原生form未指定method时的默认GET提交特征 - 这类问题几乎都是因为Axios代码绑定在表单submit事件上,没有调用
e.preventDefault()拦截默认提交行为,导致点击按钮时,浏览器先触发了表单的同步GET提交,直接打断了Axios的异步POST请求,后者根本没有机会发出去。
2. 路由顺序错误,通配路由提前拦截请求
Rails按routes.rb中的书写顺序从上到下匹配路由,先命中的规则优先生效。
- 你配置的
GET /:topic(.:format) main#default是无约束的通配GET路由,且写在了所有其他单段路径的路由之前,会直接拦截所有匹配单段路径的GET请求——包括误触发的GET /post - 这就解释了为什么请求最终走了
MainController#default:因为收到的是GET请求,不会匹配POST /post的路由规则,而是被提前出现的通配GET路由接住。
修复步骤
拦截表单默认提交行为
在submit事件的回调最开头加上event.preventDefault(),阻止浏览器原生的表单同步提交,确保Axios的POST请求正常发出。可在浏览器Network面板检查请求:确认请求方法是POST、请求载荷是Axios传入的JSON对象,排除被默认提交打断的问题。调整路由书写顺序,把通配路由放到最后
Rails的路由匹配逻辑是「越具体的规则越要靠前,通配规则永远放在最后」。你当前把GET /:topic的通配路由放在了comment、post等具体路径路由的前面,会导致大量原本应该匹配固定路由的请求被错误拦截。
调整后的路由顺序逻辑参考:# 优先级最高:所有带明确路径、固定方法的路由 root 'main#default' post '/comment', to: 'comment#create' get '/comment/new', to: 'comment#new' get '/comment/:id', to: 'comment#show' post '/post', to: 'post#create' get '/post/new', to: 'post#new' get '/:topic/:post', to: 'post#show' # 优先级最低:无固定路径的通配路由 get '/:topic', to: 'main#default'调整后,所有固定路径的请求会先匹配到对应规则,通配路由只会拦截前面所有规则都没有命中的GET请求。
补充Axios的CSRF令牌适配
Rails的POST请求默认要求校验CSRF令牌,如果Axios没有携带对应令牌,就算POST请求正常发出,也会被防护机制拦截,无法走到控制器逻辑。可通过全局配置Axios,从页面的<meta name="csrf-token">标签中读取令牌值,作为X-CSRF-Token请求头发送给后端。
内容的提问来源于stack exchange,提问作者LinkOfCode
相关产品推荐
相关产品推荐

