Consider the following code
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
When I request Users#show it renders {"error":"text"}
just fine.
But if I change unauthenticated
to
def unauthenticated(_error)
render json: { error: 'text' }, status: :unauthorized
end
And the resource responds with {"status":500,"error":"Internal Server Error"}
.
The stack trace:
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'
So calling render json: {}
in the handler causes the same error to be raised again. But at the same time render plain: ''
does not.
What happens when I change key from plain
to json
and how to make it respond with :unauthorized
instead of server error when using JSON?
I was using active_model_serializers library for rendering JSON. It uses scope
option of render
as a method name to invoke and it is current_user
by default . So the library invoked current_user
method again when I called render json: ...
leading to the error.
I've changed unauthenticated
method to
def unauthenticated(_error)
render json: { error: 'text' }, status: :unauthorized, scope: nil
end
and it began to work as expected.
Based on the information you have given, the problem is most likely how you use rescue_from
The request which triggers the error have to be a JSON request in order for this to work. For example if you try to login from a form it's usually by default a HTMl request. A way to confirm this is to use raise request.inspect
in the controller method. If this is the case, there is no easy fix and you will have to fix the request it self or just support both.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.