aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib
diff options
context:
space:
mode:
authorSantiago Pastorino <santiago@wyeworks.com>2015-12-09 15:26:46 -0300
committerSantiago Pastorino <santiago@wyeworks.com>2015-12-09 15:26:46 -0300
commitb11bca98bf5431ce9522c6b5707f51cd8d7f401c (patch)
treef665325e17cb88cdc8b8ae3ef8750806a02ed0c3 /actionpack/lib
parentb05801754f6423a1d90954ef3f6e2f5dc55c6320 (diff)
parentcdb7a8477ff19f8ed6f549cedc901bd5934a61e8 (diff)
downloadrails-b11bca98bf5431ce9522c6b5707f51cd8d7f401c.tar.gz
rails-b11bca98bf5431ce9522c6b5707f51cd8d7f401c.tar.bz2
rails-b11bca98bf5431ce9522c6b5707f51cd8d7f401c.zip
Merge pull request #20831 from jmbejar/rails-api-json-error-response
Rails API: Ability to return error responses in json format also in development
Diffstat (limited to 'actionpack/lib')
-rw-r--r--actionpack/lib/action_dispatch/http/mime_negotiation.rb9
-rw-r--r--actionpack/lib/action_dispatch/middleware/debug_exceptions.rb105
2 files changed, 81 insertions, 33 deletions
diff --git a/actionpack/lib/action_dispatch/http/mime_negotiation.rb b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
index 7acf91902d..0152c17ed4 100644
--- a/actionpack/lib/action_dispatch/http/mime_negotiation.rb
+++ b/actionpack/lib/action_dispatch/http/mime_negotiation.rb
@@ -67,6 +67,8 @@ module ActionDispatch
v = if params_readable
Array(Mime[parameters[:format]])
+ elsif format = format_from_path_extension
+ Array(Mime[format])
elsif use_accept_header && valid_accept_header
accepts
elsif xhr?
@@ -160,6 +162,13 @@ module ActionDispatch
def use_accept_header
!self.class.ignore_accept_header
end
+
+ def format_from_path_extension
+ path = @env['action_dispatch.original_path'] || @env['PATH_INFO']
+ if match = path && path.match(/\.(\w+)\z/)
+ match.captures.first
+ end
+ end
end
end
end
diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
index 66bb74b9c5..b55c937e0c 100644
--- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
+++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb
@@ -38,9 +38,10 @@ module ActionDispatch
end
end
- def initialize(app, routes_app = nil)
- @app = app
- @routes_app = routes_app
+ def initialize(app, routes_app = nil, response_format = :default)
+ @app = app
+ @routes_app = routes_app
+ @response_format = response_format
end
def call(env)
@@ -66,41 +67,79 @@ module ActionDispatch
log_error(request, wrapper)
if request.get_header('action_dispatch.show_detailed_exceptions')
- traces = wrapper.traces
-
- trace_to_show = 'Application Trace'
- if traces[trace_to_show].empty? && wrapper.rescue_template != 'routing_error'
- trace_to_show = 'Full Trace'
+ case @response_format
+ when :api
+ render_for_api_application(request, wrapper)
+ when :default
+ render_for_default_application(request, wrapper)
end
+ else
+ raise exception
+ end
+ end
- if source_to_show = traces[trace_to_show].first
- source_to_show_id = source_to_show[:id]
- end
+ def render_for_default_application(request, wrapper)
+ template = create_template(request, wrapper)
+ file = "rescues/#{wrapper.rescue_template}"
- template = DebugView.new([RESCUES_TEMPLATE_PATH],
- request: request,
- exception: wrapper.exception,
- traces: traces,
- show_source_idx: source_to_show_id,
- trace_to_show: trace_to_show,
- routes_inspector: routes_inspector(exception),
- source_extracts: wrapper.source_extracts,
- line_number: wrapper.line_number,
- file: wrapper.file
- )
- file = "rescues/#{wrapper.rescue_template}"
-
- if request.xhr?
- body = template.render(template: file, layout: false, formats: [:text])
- format = "text/plain"
- else
- body = template.render(template: file, layout: 'rescues/layout')
- format = "text/html"
- end
- render(wrapper.status_code, body, format)
+ if request.xhr?
+ body = template.render(template: file, layout: false, formats: [:text])
+ format = "text/plain"
else
- raise exception
+ body = template.render(template: file, layout: 'rescues/layout')
+ format = "text/html"
end
+ render(wrapper.status_code, body, format)
+ end
+
+ def render_for_api_application(request, wrapper)
+ body = {
+ status: wrapper.status_code,
+ error: Rack::Utils::HTTP_STATUS_CODES.fetch(
+ wrapper.status_code,
+ Rack::Utils::HTTP_STATUS_CODES[500]
+ ),
+ exception: wrapper.exception.inspect,
+ traces: wrapper.traces
+ }
+
+ content_type = request.formats.first
+ to_format = "to_#{content_type.to_sym}"
+
+ if content_type && body.respond_to?(to_format)
+ formatted_body = body.public_send(to_format)
+ format = content_type
+ else
+ formatted_body = body.to_json
+ format = Mime[:json]
+ end
+
+ render(wrapper.status_code, formatted_body, format)
+ end
+
+ def create_template(request, wrapper)
+ traces = wrapper.traces
+
+ trace_to_show = 'Application Trace'
+ if traces[trace_to_show].empty? && wrapper.rescue_template != 'routing_error'
+ trace_to_show = 'Full Trace'
+ end
+
+ if source_to_show = traces[trace_to_show].first
+ source_to_show_id = source_to_show[:id]
+ end
+
+ DebugView.new([RESCUES_TEMPLATE_PATH],
+ request: request,
+ exception: wrapper.exception,
+ traces: traces,
+ show_source_idx: source_to_show_id,
+ trace_to_show: trace_to_show,
+ routes_inspector: routes_inspector(wrapper.exception),
+ source_extracts: wrapper.source_extracts,
+ line_number: wrapper.line_number,
+ file: wrapper.file
+ )
end
def render(status, body, format)