Rails中如何设置请求mode为no-cors?重定向触发CORS的原因?
问题描述
视图代码
<%= link_to "Angebot als PDF", redirect_to_offer_pdf_offer_path(offer, project_id: @project.id), method: :get, class:"dropdown-item" %>
Offers控制器动作代码
url = get_url_on_other_host() if url redirect_to url, allow_other_host: true end
浏览器控制台错误
Access to fetch at '<other_host_url>' (redirected from '<the_action_url') from origin '<my_host>' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
用户疑问
- 如何设置请求的mode为
no-cors? - 为什么简单的GET重定向也需要进行CORS检查?原以为只有DELETE或PUT这类请求才需要。
解决方案与解释
一、设置请求mode为no-cors
你用的link_to生成的普通链接默认是浏览器同步跳转,不会触发CORS问题。出现错误说明这个请求是通过JavaScript异步发起的(比如Turbo自动转换的导航请求,或者自定义的点击事件)。有两种处理方式:
方式1:用JavaScript手动发起带no-cors的请求
// 给目标链接绑定点击拦截事件 document.querySelector('.dropdown-item[href*="redirect_to_offer_pdf"]').addEventListener('click', function(e) { e.preventDefault(); // 阻止默认跳转行为 fetch(this.href, { method: 'GET', mode: 'no-cors' // 开启no-cors模式 }).then(response => { // 注意:no-cors模式下无法读取响应内容,只能做基础跳转处理 if (response.type === 'opaque') { window.location.href = this.href; } }); });
方式2:禁用Turbo异步处理
如果是Rails的Turbo导致的异步请求,直接给链接加data-turbo="false"属性,让浏览器恢复同步跳转,就不会触发CORS检查:
<%= link_to "Angebot als PDF", redirect_to_offer_pdf_offer_path(offer, project_id: @project.id), method: :get, class:"dropdown-item", data: { turbo: false } %>
二、GET重定向触发CORS的原因
CORS规则不是只针对PUT/DELETE这类非简单请求,核心判断依据是请求的发起方式:
- 如果是浏览器直接打开链接的同步跳转,跨域重定向完全允许,不会触发CORS检查
- 如果是通过fetch/XHR/Turbo这类异步方式发起的请求,当服务器返回重定向到跨域地址时,浏览器会自动跟随重定向向跨域地址发请求,此时整个异步请求的最终响应来自跨域资源,浏览器就会要求目标服务器返回
Access-Control-Allow-Origin头,否则就会报错。
你遇到的情况,大概率是Rails默认启用的Turbo把普通链接转换成了异步请求,才触发了跨域检查。
内容的提问来源于stack exchange,提问作者user7996789
相关产品推荐
相关产品推荐

