You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

React/Rails应用Fetch访问Rails后端遇500错误,求排查解决

React/Rails API 连接失败排查与解决

问题背景

在React/Rails应用中尝试访问API后端,参考某过时教程调整后仍无法正常连接,需排查错误并找到解决方法。

错误信息

前端Fetch控制台错误

Uncaught (in promise) SyntaxError: Unexpected token '<', "<!DOCTYPE "... is not valid JSON

Rails服务器日志错误

Started GET "/api/v1/playlists/index" for ::1 at 2024-09-05 08:59:11 -0400
Processing by Api::V1::PlaylistsController#index as */*
  Playlist Load (0.4ms)  SELECT "playlists".* FROM "playlists"
  ↳ app/controllers/api/v1/playlists_controller.rb:5:in `index'
  ActiveStorage::Attachment Load (0.2ms)  SELECT "active_storage_attachments".* FROM "active_storage_attachments" WHERE "active_storage_attachments"."record_id" = ? AND "active_storage_attachments"."record_type" = ? AND "active_storage_attachments"."name" = ? LIMIT ?  [["record_id", 1], ["record_type", "Playlist"], ["name", "image"], ["LIMIT", 1]]
  ↳ app/controllers/api/v1/playlists_controller.rb:5:in `index'
  ActiveStorage::Blob Load (0.1ms)  SELECT "active_storage_blobs".* FROM "active_storage_blobs" WHERE "active_storage_blobs"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
  ↳ app/controllers/api/v1/playlists_controller.rb:5:in `index'
Completed 500 Internal Server Error in 51ms (ActiveRecord: 0.7ms | Allocations: 7845)

fatal (exception reentered):

相关代码片段

React组件:javascript/components/Playlists.jsx(截断版)

import { Table, message, Popconfirm } from "antd";
import React from "react";

class Playlists extends React.Component {

  ...

  loadPlaylists = () => {
    const url = "api/v1/playlists/index";
    fetch(url)
      .then((data) => {
        if (data.ok) {
          return data.json();
        }
        console.log(data.json())
        throw new Error("Network error.");
      })

      ...

  };

  ...

  render() {
    return (
      <>
        <Table className="table-striped-rows" dataSource={this.state.playlists} columns={this.columns} pagination={{ pageSize: 5 }} />

      </>
    );
  }
}

export default Playlists;

Rails控制器:controllers/api/v1/playlists_controller.rb

class Api::V1::PlaylistsController < ApplicationController
  # GET /playlists or /playlists.json
  def index
    @playlists = Playlist.all
    render json: @playlists
  end
end

Rails路由:routes.rb

Rails.application.routes.draw do
  root 'page#index'

  namespace :api do
    namespace :v1 do
      get 'playlists/index'
      post 'playlists/create'
      delete 'playlists/:id', to: 'playlists#destroy'
    end
  end
end

更新发现

将控制器中的Playlist.all替换为其他模型(如Track模型,包含YouTube视频ID及播放列表关联)时,接口可正常工作:

class Api::V1::PlaylistsController < ApplicationController
  # GET /playlists or /playlists.json
  def index
    @playlists = Track.all
    render json: @playlists
  end
end

此时无500错误,仅因字段不同导致表格内容不完整,但能正常获取Track数据。


解决步骤

1. 定位核心问题

前端收到HTML而非JSON,说明Rails在触发500错误时返回了默认错误页面,而非JSON响应。结合更新发现,问题出在Playlist模型的JSON序列化过程中——默认序列化无法处理模型中的ActiveStorage附件关联。

2. 修复Playlist模型序列化问题

方法一:临时排除附件字段验证

先验证是否为附件序列化导致的错误,修改控制器代码:

def index
  @playlists = Playlist.all
  render json: @playlists.as_json(except: [:image]) # 排除ActiveStorage关联字段
end

如果请求正常,说明确实是附件序列化的问题。

方法二:显式包含ActiveStorage附件信息

如果需要返回附件数据,调整序列化逻辑:

def index
  @playlists = Playlist.all
  render json: @playlists, include: { image_attachment: { include: :blob } }
end

方法三:使用自定义序列化器(推荐)

安装active_model_serializers gem,创建自定义序列化器精确控制返回字段:

# app/serializers/playlist_serializer.rb
class PlaylistSerializer < ActiveModel::Serializer
  attributes :id, :name, :description # 按需添加字段
  has_one :image_attachment, serializer: ActiveStorageAttachmentSerializer
end

控制器中使用序列化器:

def index
  @playlists = Playlist.all
  render json: @playlists, serializer: PlaylistSerializer
end

3. 优化API错误响应

在API控制器中添加错误捕获,确保500错误时返回JSON而非HTML:

class Api::V1::PlaylistsController < ApplicationController
  rescue_from StandardError, with: :render_internal_server_error

  def index
    @playlists = Playlist.all
    render json: @playlists
  end

  private

  def render_internal_server_error(exception)
    render json: { error: exception.message }, status: :internal_server_error
  end
end

4. 路由规范优化(可选)

遵循Rails RESTful规范,调整路由:

Rails.application.routes.draw do
  root 'page#index'

  namespace :api do
    namespace :v1 do
      resources :playlists, only: [:index, :create, :destroy]
    end
  end
end

同时更新React中的请求URL为/api/v1/playlists。


内容的提问来源于stack exchange,提问作者Jillian Hoenig

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 20:14:52