Rails 6 API对接React时CORS请求返回200但无法读取响应数据
Rails 6 API对接React前端跨域请求返回200但无法读取数据问题
问题背景
- 后端采用Ruby on Rails 6开发REST API,前端为运行在
localhost:3005的React应用 - 接口测试情况:通过Postman、Curl测试GET接口均可返回预期响应;浏览器网络面板可查看到后端返回正确的餐品JSON数据,但页面DOM未渲染对应内容,fetch返回的response对象无法正常读取,
response.ok属性值为false,状态码显示200
现象截图
- Firefox控制台截图:

- 后端返回数据截图:

- DOM未渲染数据截图:

相关代码与响应内容
1. React前端useEffect数据请求逻辑
useEffect(() => { const fetchMeals = async () => { const response = await fetch("http://localhost:3000/meals.json", { 'method': 'GET', 'mode': 'no-cors', 'headers': { 'Origin': 'localhost:3000', 'Access-Control-Allow-Origin': '*', } }); if (!response.ok) { throw new Error("The data could not be shown"); } const responseData = await response.json(); const loadedMeals = []; for (const key in responseData) { loadedMeals.push({ id: key, name: responseData[key].name, description: responseData[key].description, price: responseData[key].price, }); } if (!loadedMeals.length) { throw new Error("No products found to display"); } else { setMeals(loadedMeals); setIsLoading(false); } }; fetchMeals().catch((error) => { setIsLoading(false); setHttpError(error.message); }); }, []);
2. Rails后端cors跨域配置
配置文件路径:config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do allow do origins 'localhost:3005', '127.0.0.1:3005' resource '*', headers: :any, methods: [:get, :post, :put, :patch, :delete, :options, :head] end end
3. MealsController控制器代码
class MealsController < ApplicationController #get /meals def index @meals = Meal.all render json: @meals end end
4. Meal模型代码
class Meal < ApplicationRecord def as_json(options = {}) super(:only => [:id, :name, :description, :price]) end end
5. 后端实际返回JSON内容
[ { "id": 1, "name": "Cheese and Loroco", "description": "Corn made pupusa with cheese", "price": "1.25" }, { "id": 2, "name": "Cheese and red deans", "description": "Corn made pupusa with cheese and beans", "price": "0.65" }, { "id": 3, "name": "Pork, cheese and red beans", "description": "Corn made pupusa with a mix of pork,cheese and red beans", "price": "0.85" }, { "id": 4, "name": "Soda", "description": "Salvadoran soda beverages", "price": "0.65" }, { "id": 5, "name": "Coffee", "description": "High quality roasted salvadoran coffee", "price": "1.1" } ]
核心疑问
- 浏览器网络面板已明确显示后端返回了正确的响应数据,为何前端代码无法读取
- 请求返回200状态码的情况下,
response.ok为false、无法解析响应JSON的原因
问题根因
核心错误是前端fetch请求配置了mode: 'no-cors':
- 该模式下浏览器会正常发送请求、接收响应,但完全禁止前端JavaScript读取响应内容、状态头等任何信息,返回的是opaque(不透明)响应对象。这类对象的
ok属性固定为false,status固定为0,响应体不可读,这就是网络面板能看到数据、但代码拿不到的直接原因。 - 请求头里手动添加的
Origin和Access-Control-Allow-Origin完全无效:Origin是浏览器自动生成的安全类请求头,禁止前端代码手动篡改;Access-Control-Allow-Origin是后端返回的响应头字段,放在请求里没有任何作用。 - 后端的CORS配置本身是正确的,已经放行了3005端口的前端请求,完全不需要使用no-cors模式。
修复方案
- 调整前端fetch请求配置,删除
mode: 'no-cors'配置项,同时删除headers里手动加的两个无效字段,简化后的请求代码如下:
const response = await fetch("http://localhost:3000/meals.json", { method: 'GET' });
- 检查后端依赖与服务状态:确认Gemfile中已添加
gem 'rack-cors'并执行过bundle install,修改cors配置后必须重启Rails服务才能让配置生效。 - 优化数据处理逻辑:后端直接返回的是数组结构的餐品数据,不需要用
for...in遍历对象转数组,拿到responseData后可以直接赋值使用,无需额外格式转换。
内容的提问来源于stack exchange,提问作者htamayo
相关产品推荐
相关产品推荐

