将 "render" 键从 "plain" 更改为 "json" 会导致服务器错误
Changing "render" key from "plain" to "json" causes server error
考虑以下代码
class AuthenticatedController < ApplicationController
rescue_from InvalidCredentials, with: :unauthenticated
def current_user
raise InvalidCredentials
end
private
def unauthenticated(_error)
render plain: { error: 'text' }.to_json, status: :unauthorized
end
end
class UsersController < AuthenticatedController
def show
render json: current_user
end
end
当我请求 Users#show 时,它呈现 {"error":"text"}
就好了。
但是如果我把unauthenticated
改成
def unauthenticated(_error)
render json: { error: 'text' }, status: :unauthorized
end
资源响应 {"status":500,"error":"Internal Server Error"}
。
堆栈跟踪:
Started GET "/api/v1/user" for ::1 at 2021-08-25 12:24:30 +0300
Processing by Api::V1::UsersController#show as JSON
Parameters: {"user"=>{}}
Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms | Allocations: 214)
InvalidCredentials (InvalidCredentials):
app/controllers/users_controller.rb:in `show'
app/controllers/authenticated_controller.rb:in `current_user'
app/controllers/authenticated_controller.rb:in `unauthenticated'
因此在处理程序中调用 render json: {}
会导致再次引发相同的错误。但同时 render plain: ''
没有。
当我将密钥从 plain
更改为 json
时会发生什么,以及在使用 JSON 时如何使其响应 :unauthorized
而不是服务器错误?
根据您提供的信息,问题很可能是您如何使用 rescue_from
触发错误的请求必须是 JSON 请求才能使其正常工作。例如,如果您尝试从表单登录,默认情况下通常是 HTMl 请求。确认这一点的一种方法是在控制器方法中使用 raise request.inspect
。如果是这种情况,则没有简单的修复方法,您将不得不自行修复请求或同时支持两者。
我正在使用 active_model_serializers 库进行渲染 JSON。
它使用 render
的 scope
选项作为要调用的方法名称,它是 current_user
by default。因此,当我调用 render json: ...
导致错误时,库再次调用了 current_user
方法。
我已将 unauthenticated
方法更改为
def unauthenticated(_error)
render json: { error: 'text' }, status: :unauthorized, scope: nil
end
它开始按预期工作。
考虑以下代码
class AuthenticatedController < ApplicationController
rescue_from InvalidCredentials, with: :unauthenticated
def current_user
raise InvalidCredentials
end
private
def unauthenticated(_error)
render plain: { error: 'text' }.to_json, status: :unauthorized
end
end
class UsersController < AuthenticatedController
def show
render json: current_user
end
end
当我请求 Users#show 时,它呈现 {"error":"text"}
就好了。
但是如果我把unauthenticated
改成
def unauthenticated(_error)
render json: { error: 'text' }, status: :unauthorized
end
资源响应 {"status":500,"error":"Internal Server Error"}
。
堆栈跟踪:
Started GET "/api/v1/user" for ::1 at 2021-08-25 12:24:30 +0300
Processing by Api::V1::UsersController#show as JSON
Parameters: {"user"=>{}}
Completed 500 Internal Server Error in 1ms (ActiveRecord: 0.0ms | Allocations: 214)
InvalidCredentials (InvalidCredentials):
app/controllers/users_controller.rb:in `show'
app/controllers/authenticated_controller.rb:in `current_user'
app/controllers/authenticated_controller.rb:in `unauthenticated'
因此在处理程序中调用 render json: {}
会导致再次引发相同的错误。但同时 render plain: ''
没有。
当我将密钥从 plain
更改为 json
时会发生什么,以及在使用 JSON 时如何使其响应 :unauthorized
而不是服务器错误?
根据您提供的信息,问题很可能是您如何使用 rescue_from
触发错误的请求必须是 JSON 请求才能使其正常工作。例如,如果您尝试从表单登录,默认情况下通常是 HTMl 请求。确认这一点的一种方法是在控制器方法中使用 raise request.inspect
。如果是这种情况,则没有简单的修复方法,您将不得不自行修复请求或同时支持两者。
我正在使用 active_model_serializers 库进行渲染 JSON。
它使用 render
的 scope
选项作为要调用的方法名称,它是 current_user
by default。因此,当我调用 render json: ...
导致错误时,库再次调用了 current_user
方法。
我已将 unauthenticated
方法更改为
def unauthenticated(_error)
render json: { error: 'text' }, status: :unauthorized, scope: nil
end
它开始按预期工作。