How to Return Correct Http Error Codes from Ruby on Rails Application

How to return correct HTTP error codes from Ruby on Rails application

You should render page with correct status.

render(:file => File.join(Rails.root, 'public/403.html'), :status => 403, :layout => false)

Trigger a HTTP error in Rails

In your controller code add the following line:

render :status => :forbidden, :text => "Forbidden fruit"

Refer to this page for http code to symbol mapping.

Store response HTTP status code after exception in Rails

I finally solved adding a middleware (here some datails on how rails middlewares work).
In detail, in config/application.rb, I added:

config.middleware.insert_before "Rails::Rack::Logger","StoreStatus"

the api controller was

class Api::ApiController < ActionController::Base
before_action :set_current_rest_request
private
def set_current_rest_request
@current_rest_request = RestRequest.new
request.env[:current_rest_request] = @current_rest_request
end
end

and I added the file lib/store_status.rb with the following code:

class StoreStatus
def initialize(app)
@app = app
end

def call(env)
data = @app.call(env)
if (env[:current_rest_request])
rest_request = env[:current_rest_request]
rest_request.http_status_code = data[0]
rest_request.save
end
data
end
end

Please notice that there may be some syntax error because this code has been obtained refactoring a code which contains other useless complexity for this question.

Return a specific http status code in Rails

For the entire application:

# ApplicationController
before_filter :return_unavailable_status

private
def return_unavailable_status
render :nothing => true, :status => :service_unavailable
end

If you wanted a custom error page, you could do:

render 'custom_unavailable_page', :status => :service_unavailable    

If you don't want it for specific controllers:

# SomeController
skip_before_filter :return_unavailable_status

HTTP status code for this case (400 or 422)

When I build API, usually I use 422 aka :unprocessable_entity for validation errors.

In my opinion, :unprocessable_entity looks more explicit.

Is there a way to get response on error with HTTPClient in Ruby?

You're using get_content which skips a few steps and returns the content. Instead step back and use get which will return a more complete response structure that includes, among other things, the status field you want:

def stock(product, location)
response = @client.get("stock/#{product}/#{location}")

body = response.body
status = response.status
end

Change status code Rails

I found a solution to my problem from the Ruby on Rails backend side that is generalized for the whole application which is required as a lot of controllers would also give 401 and not only devise.

I have used Rack middleware by doing the following:

app/middleware/unauthorized_to_forbidden.rb

class   UnauthorizedToForbidden
def initialize(app)
@app = app
end

def call(env)
status, headers, response = @app.call(env)
if(status == 401)
status = 403
end
[status, headers, response]
end
end

config/application.rb

class Application < Rails::Application
config.middleware.use "UnauthorizedToForbidden"
end

Now UnauthorizedToForbidden is at the bottom of the Rack stack and gets executed at the very end before the response is actually sent to the user. It basically changes the status code if it's 401 to 403.

HTTP status code when sending email failed

502

bad_gateway

Typically used for upstream server failure.

Here's some more info: https://airbrake.io/blog/http-errors/502-bad-gateway-error

a 502 Bad Gateway Error means that a server that is upstream to one that you (the client) are connecting to has run into trouble. In this scenario, this means that the server providing the 502 Bad Gateway Error is acting as a gateway



Related Topics



Leave a reply



Submit