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

Rails 7生产环境控制器异常无响应问题求助

问题描述

我有一个Rails 7.0.3.1应用,同时作为JS SPA的HTML服务器和对应API服务。开发环境下JSON API的错误能正确渲染(包含错误信息、调用栈等),但在生产环境或设置config.consider_all_requests_local = false时,Rails仅返回带500状态码的空白响应,完全不返回错误页面。尝试设置exceptions_app和配置路由均无效。

示例代码

Trips控制器

class TripsController < ApplicationController
  def show
    raise StandardError, 'Tripped and fell'
  end
end

路由配置

Rails.application.routes.draw do
  get "/trip/:error" => 'trips#show'
end

空白响应截图

空白响应页面

版本信息

  • Rails 7.0.3.1
  • Ruby 3.0.2p107 (2021-07-07 revision 0db68f0233)

服务器控制台日志

=> Rails 7.0.3.1 application starting in development 
=> Run `bin/rails server --help` for more startup options
Puma starting in single mode...
* Puma version: 5.6.4 (ruby 3.0.2-p107) ("Birdie's Version")
*  Min threads: 0
*  Max threads: 1
*  Environment: development
*          PID: 88888
* Listening on http://127.0.0.1:3000
* Listening on http://[::1]:3000
Use Ctrl-C to stop
Started GET "/trip/500" for ::1 at 8888-88-88 88:88:88 -8888
  ActiveRecord::SchemaMigration Pluck (1.2ms)  SELECT "schema_migrations"."version" FROM "schema_migrations" ORDER BY "schema_migrations"."version" ASC
Processing by TripsController#show as HTML
  Parameters: {"error"=>"500"}
Completed 500 Internal Server Error in 8ms (ActiveRecord: 0.0ms | Allocations: 3293)


  
StandardError (Tripped and fell):
  
app/controllers/trips_controller.rb:6:in `show'
解决方法

1. 区分请求格式处理错误

Rails默认根据请求的Accept头返回对应格式的响应。从日志可见当前请求是HTML格式,需在控制器中统一处理不同格式的错误:

class ApplicationController < ActionController::Base
  rescue_from StandardError, with: :handle_error

  private

  def handle_error(exception)
    if request.format.json?
      render json: { error: exception.message, backtrace: exception.backtrace }, status: :internal_server_error
    else
      render plain: exception.message, status: :internal_server_error
    end
  end
end

2. 配置自定义异常处理程序

在config/application.rb或对应环境配置文件中设置:

config.exceptions_app = ->(env) { ErrorsController.action(:show).call(env) }

创建ErrorsController:

class ErrorsController < ApplicationController
  def show
    status_code = request.env['action_dispatch.exception']&.status_code || request.status_code
    message = case status_code
              when 500 then '服务器内部错误'
              when 404 then '资源未找到'
              else '请求错误'
              end

    if request.format.json?
      render json: { error: message }, status: status_code
    else
      render plain: message, status: status_code
    end
  end
end

同时在路由中添加:

get '/errors/:status', to: 'errors#show', constraints: { status: /\d{3}/ }

3. 确保生产环境静态错误页面存在

Rails生产环境默认使用public目录下的静态错误页面(如500.html、404.html),缺失会导致空白响应。可生成默认页面:

rails generate error_pages

或手动创建public/500.html并添加自定义内容。

4. 检查环境配置参数

确保config/environments/production.rb中:

config.consider_all_requests_local = false
config.action_dispatch.show_exceptions = true

内容的提问来源于stack exchange,提问作者Eric Prostko

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:45:39