Merge pull request #3183 from riking/json-errors-2

Consolidate custom exception handling
This commit is contained in:
Sam 2015-02-23 16:58:05 +11:00
commit 5266ad4539
3 changed files with 43 additions and 23 deletions

View File

@ -76,7 +76,7 @@ class ApplicationController < ActionController::Base
# Some exceptions
class RenderEmpty < Exception; end
# Render nothing unless we are an xhr request
# Render nothing
rescue_from RenderEmpty do
render 'default/empty'
end
@ -93,40 +93,43 @@ class ApplicationController < ActionController::Base
time_left = I18n.t("rate_limiter.hours", count: (e.available_in / 1.hour.to_i))
end
render json: {errors: [I18n.t("rate_limiter.too_many_requests", time_left: time_left)]}, status: 429
render_json_error I18n.t("rate_limiter.too_many_requests", time_left: time_left), type: :rate_limit, status: 429
end
rescue_from Discourse::NotLoggedIn do |e|
raise e if Rails.env.test?
if request.get?
redirect_to "/"
if (request.format && request.format.json?) || request.xhr? || !request.get?
rescue_discourse_actions(:not_logged_in, 403, true)
else
render status: 403, json: failed_json.merge(message: I18n.t(:not_logged_in))
redirect_to "/"
end
end
rescue_from Discourse::NotFound do
rescue_discourse_actions("[error: 'not found']", 404) # TODO: this breaks json responses
rescue_discourse_actions(:not_found, 404)
end
rescue_from Discourse::InvalidAccess do
rescue_discourse_actions("[error: 'invalid access']", 403, true) # TODO: this breaks json responses
rescue_discourse_actions(:invalid_access, 403, true)
end
rescue_from Discourse::ReadOnly do
render status: 405, json: failed_json.merge(message: I18n.t("read_only_mode_enabled"))
render_json_error I18n.t('read_only_mode_enabled'), type: :read_only, status: 405
end
def rescue_discourse_actions(message, error, include_ember=false)
if request.format && request.format.json?
# TODO: this doesn't make sense. Stuffing an html page into a json response will cause
# $.parseJSON to fail in the browser. Also returning text like "[error: 'invalid access']"
# from the above rescue_from blocks will fail because that isn't valid json.
render status: error, layout: false, text: (error == 404) ? build_not_found_page(error) : message
def rescue_discourse_actions(type, status_code, include_ember=false)
if (request.format && request.format.json?) || (request.xhr?)
# HACK: do not use render_json_error for topics#show
if request.params[:controller] == 'topics' && request.params[:action] == 'show'
return render status: status_code, layout: false, text: (status_code == 404) ? build_not_found_page(status_code) : I18n.t(type)
end
render_json_error I18n.t(type), type: type, status: status_code
else
render text: build_not_found_page(error, include_ember ? 'application' : 'no_ember')
render text: build_not_found_page(status_code, include_ember ? 'application' : 'no_ember')
end
end
@ -318,8 +321,17 @@ class ApplicationController < ActionController::Base
MultiJson.dump(serializer)
end
def render_json_error(obj)
render json: MultiJson.dump(create_errors_json(obj)), status: 422
# Render action for a JSON error.
#
# obj - a translated string, an ActiveRecord model, or an array of translated strings
# opts:
# type - a machine-readable description of the error
# status - HTTP status code to return
def render_json_error(obj, opts={})
if opts.is_a? Fixnum
opts = {status: opts}
end
render json: MultiJson.dump(create_errors_json(obj, opts[:type])), status: opts[:status] || 422
end
def success_json

View File

@ -118,6 +118,8 @@ en:
not_enough_space_on_disk: "There is not enough space on disk to upload this backup."
not_logged_in: "You need to be logged in to do that."
not_found: "The requested URL or resource could not be found."
invalid_access: "You are not permitted to view the requested resource."
read_only_mode_enabled: "The site is in read only mode. Interactions are disabled."
too_many_replies:

View File

@ -1,6 +1,14 @@
module JsonError
def create_errors_json(obj)
def create_errors_json(obj, type=nil)
errors = create_errors_array obj
errors[:error_type] = type if type
errors
end
private
def create_errors_array(obj)
# If we're passed a string, assume that is the error message
return {errors: [obj]} if obj.is_a?(String)
@ -21,10 +29,8 @@ module JsonError
JsonError.generic_error
end
private
def self.generic_error
{errors: [I18n.t('js.generic_error')]}
end
def self.generic_error
{errors: [I18n.t('js.generic_error')]}
end
end