actionpack 5.0.7.2 → 5.1.0.beta1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of actionpack might be problematic. Click here for more details.

Files changed (128) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +189 -1002
  3. data/MIT-LICENSE +1 -1
  4. data/README.rdoc +1 -1
  5. data/lib/abstract_controller.rb +3 -3
  6. data/lib/abstract_controller/base.rb +10 -12
  7. data/lib/abstract_controller/caching.rb +6 -3
  8. data/lib/abstract_controller/caching/fragments.rb +1 -1
  9. data/lib/abstract_controller/callbacks.rb +2 -43
  10. data/lib/abstract_controller/collector.rb +2 -2
  11. data/lib/abstract_controller/helpers.rb +19 -19
  12. data/lib/abstract_controller/rendering.rb +9 -11
  13. data/lib/abstract_controller/translation.rb +3 -3
  14. data/lib/action_controller.rb +15 -13
  15. data/lib/action_controller/api.rb +3 -3
  16. data/lib/action_controller/base.rb +7 -12
  17. data/lib/action_controller/caching.rb +1 -1
  18. data/lib/action_controller/log_subscriber.rb +2 -2
  19. data/lib/action_controller/metal.rb +34 -43
  20. data/lib/action_controller/metal/conditional_get.rb +10 -9
  21. data/lib/action_controller/metal/data_streaming.rb +8 -9
  22. data/lib/action_controller/metal/etag_with_flash.rb +16 -0
  23. data/lib/action_controller/metal/etag_with_template_digest.rb +15 -15
  24. data/lib/action_controller/metal/exceptions.rb +4 -14
  25. data/lib/action_controller/metal/flash.rb +1 -1
  26. data/lib/action_controller/metal/force_ssl.rb +6 -6
  27. data/lib/action_controller/metal/head.rb +13 -19
  28. data/lib/action_controller/metal/helpers.rb +6 -6
  29. data/lib/action_controller/metal/http_authentication.rb +22 -23
  30. data/lib/action_controller/metal/implicit_render.rb +2 -5
  31. data/lib/action_controller/metal/instrumentation.rb +14 -14
  32. data/lib/action_controller/metal/live.rb +15 -16
  33. data/lib/action_controller/metal/mime_responds.rb +3 -3
  34. data/lib/action_controller/metal/parameter_encoding.rb +49 -0
  35. data/lib/action_controller/metal/params_wrapper.rb +32 -32
  36. data/lib/action_controller/metal/redirecting.rb +8 -24
  37. data/lib/action_controller/metal/renderers.rb +2 -3
  38. data/lib/action_controller/metal/rendering.rb +50 -60
  39. data/lib/action_controller/metal/request_forgery_protection.rb +51 -49
  40. data/lib/action_controller/metal/rescue.rb +1 -1
  41. data/lib/action_controller/metal/streaming.rb +4 -4
  42. data/lib/action_controller/metal/strong_parameters.rb +117 -250
  43. data/lib/action_controller/metal/testing.rb +1 -1
  44. data/lib/action_controller/metal/url_for.rb +4 -4
  45. data/lib/action_controller/railtie.rb +9 -13
  46. data/lib/action_controller/renderer.rb +17 -16
  47. data/lib/action_controller/test_case.rb +75 -148
  48. data/lib/action_dispatch.rb +20 -19
  49. data/lib/action_dispatch/http/cache.rb +9 -10
  50. data/lib/action_dispatch/http/filter_parameters.rb +8 -8
  51. data/lib/action_dispatch/http/filter_redirect.rb +2 -4
  52. data/lib/action_dispatch/http/headers.rb +10 -10
  53. data/lib/action_dispatch/http/mime_negotiation.rb +17 -22
  54. data/lib/action_dispatch/http/mime_type.rb +27 -52
  55. data/lib/action_dispatch/http/parameter_filter.rb +8 -6
  56. data/lib/action_dispatch/http/parameters.rb +40 -17
  57. data/lib/action_dispatch/http/request.rb +38 -34
  58. data/lib/action_dispatch/http/response.rb +16 -16
  59. data/lib/action_dispatch/http/upload.rb +6 -10
  60. data/lib/action_dispatch/http/url.rb +48 -74
  61. data/lib/action_dispatch/journey.rb +5 -5
  62. data/lib/action_dispatch/journey/formatter.rb +8 -4
  63. data/lib/action_dispatch/journey/gtg/builder.rb +5 -5
  64. data/lib/action_dispatch/journey/gtg/simulator.rb +1 -1
  65. data/lib/action_dispatch/journey/gtg/transition_table.rb +15 -15
  66. data/lib/action_dispatch/journey/nfa/builder.rb +3 -3
  67. data/lib/action_dispatch/journey/nfa/dot.rb +2 -2
  68. data/lib/action_dispatch/journey/nfa/simulator.rb +1 -1
  69. data/lib/action_dispatch/journey/nfa/transition_table.rb +2 -2
  70. data/lib/action_dispatch/journey/nodes/node.rb +5 -5
  71. data/lib/action_dispatch/journey/parser.rb +23 -24
  72. data/lib/action_dispatch/journey/parser.y +3 -2
  73. data/lib/action_dispatch/journey/parser_extras.rb +2 -2
  74. data/lib/action_dispatch/journey/path/pattern.rb +10 -3
  75. data/lib/action_dispatch/journey/route.rb +19 -12
  76. data/lib/action_dispatch/journey/router.rb +19 -12
  77. data/lib/action_dispatch/journey/router/utils.rb +9 -9
  78. data/lib/action_dispatch/journey/scanner.rb +17 -15
  79. data/lib/action_dispatch/journey/visitors.rb +23 -23
  80. data/lib/action_dispatch/middleware/callbacks.rb +0 -12
  81. data/lib/action_dispatch/middleware/cookies.rb +39 -39
  82. data/lib/action_dispatch/middleware/debug_exceptions.rb +126 -112
  83. data/lib/action_dispatch/middleware/debug_locks.rb +8 -8
  84. data/lib/action_dispatch/middleware/exception_wrapper.rb +55 -55
  85. data/lib/action_dispatch/middleware/executor.rb +1 -1
  86. data/lib/action_dispatch/middleware/flash.rb +17 -16
  87. data/lib/action_dispatch/middleware/public_exceptions.rb +20 -20
  88. data/lib/action_dispatch/middleware/reloader.rb +3 -47
  89. data/lib/action_dispatch/middleware/remote_ip.rb +6 -8
  90. data/lib/action_dispatch/middleware/request_id.rb +6 -5
  91. data/lib/action_dispatch/middleware/session/abstract_store.rb +14 -26
  92. data/lib/action_dispatch/middleware/session/cache_store.rb +3 -3
  93. data/lib/action_dispatch/middleware/session/cookie_store.rb +35 -35
  94. data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -2
  95. data/lib/action_dispatch/middleware/show_exceptions.rb +19 -19
  96. data/lib/action_dispatch/middleware/ssl.rb +9 -27
  97. data/lib/action_dispatch/middleware/stack.rb +7 -26
  98. data/lib/action_dispatch/middleware/static.rb +13 -24
  99. data/lib/action_dispatch/railtie.rb +9 -11
  100. data/lib/action_dispatch/request/session.rb +22 -22
  101. data/lib/action_dispatch/request/utils.rb +11 -2
  102. data/lib/action_dispatch/routing.rb +8 -6
  103. data/lib/action_dispatch/routing/inspector.rb +37 -37
  104. data/lib/action_dispatch/routing/mapper.rb +296 -203
  105. data/lib/action_dispatch/routing/polymorphic_routes.rb +160 -134
  106. data/lib/action_dispatch/routing/redirection.rb +27 -22
  107. data/lib/action_dispatch/routing/route_set.rb +206 -92
  108. data/lib/action_dispatch/routing/routes_proxy.rb +2 -2
  109. data/lib/action_dispatch/routing/url_for.rb +14 -12
  110. data/lib/action_dispatch/system_test_case.rb +119 -0
  111. data/lib/action_dispatch/system_testing/browser.rb +28 -0
  112. data/lib/action_dispatch/system_testing/driver.rb +18 -0
  113. data/lib/action_dispatch/system_testing/server.rb +32 -0
  114. data/lib/action_dispatch/system_testing/test_helpers/screenshot_helper.rb +61 -0
  115. data/lib/action_dispatch/system_testing/test_helpers/setup_and_teardown.rb +20 -0
  116. data/lib/action_dispatch/testing/assertion_response.rb +6 -6
  117. data/lib/action_dispatch/testing/assertions.rb +4 -4
  118. data/lib/action_dispatch/testing/assertions/response.rb +8 -3
  119. data/lib/action_dispatch/testing/assertions/routing.rb +11 -11
  120. data/lib/action_dispatch/testing/integration.rb +47 -138
  121. data/lib/action_dispatch/testing/test_process.rb +2 -2
  122. data/lib/action_dispatch/testing/test_request.rb +16 -16
  123. data/lib/action_dispatch/testing/test_response.rb +1 -1
  124. data/lib/action_pack.rb +2 -2
  125. data/lib/action_pack/gem_version.rb +3 -3
  126. data/lib/action_pack/version.rb +1 -1
  127. metadata +20 -12
  128. data/lib/action_dispatch/middleware/params_parser.rb +0 -46
@@ -5,7 +5,7 @@ module ActionDispatch
5
5
  ESCAPE_PATH = ->(value) { Router::Utils.escape_path(value) }
6
6
  ESCAPE_SEGMENT = ->(value) { Router::Utils.escape_segment(value) }
7
7
 
8
- class Parameter < Struct.new(:name, :escaper)
8
+ Parameter = Struct.new(:name, :escaper) do
9
9
  def escape(value); escaper.call value; end
10
10
  end
11
11
 
@@ -22,7 +22,7 @@ module ActionDispatch
22
22
  @children = []
23
23
  @parameters = []
24
24
 
25
- parts.each_with_index do |object,i|
25
+ parts.each_with_index do |object, i|
26
26
  case object
27
27
  when Journey::Format
28
28
  @children << i
@@ -38,7 +38,7 @@ module ActionDispatch
38
38
  @parameters.each do |index|
39
39
  param = parts[index]
40
40
  value = hash[param.name]
41
- return ''.freeze unless value
41
+ return "".freeze unless value
42
42
  parts[index] = param.escape value
43
43
  end
44
44
 
@@ -58,7 +58,7 @@ module ActionDispatch
58
58
 
59
59
  private
60
60
 
61
- def visit node
61
+ def visit(node)
62
62
  send(DISPATCH_CACHE[node.type], node)
63
63
  end
64
64
 
@@ -98,7 +98,7 @@ module ActionDispatch
98
98
  visit(node, seed)
99
99
  end
100
100
 
101
- def visit node, seed
101
+ def visit(node, seed)
102
102
  send(DISPATCH_CACHE[node.type], node, seed)
103
103
  end
104
104
 
@@ -167,28 +167,28 @@ module ActionDispatch
167
167
  class String < FunctionalVisitor # :nodoc:
168
168
  private
169
169
 
170
- def binary(node, seed)
171
- visit(node.right, visit(node.left, seed))
172
- end
170
+ def binary(node, seed)
171
+ visit(node.right, visit(node.left, seed))
172
+ end
173
173
 
174
- def nary(node, seed)
175
- last_child = node.children.last
176
- node.children.inject(seed) { |s, c|
177
- string = visit(c, s)
178
- string << "|".freeze unless last_child == c
179
- string
180
- }
181
- end
174
+ def nary(node, seed)
175
+ last_child = node.children.last
176
+ node.children.inject(seed) { |s, c|
177
+ string = visit(c, s)
178
+ string << "|".freeze unless last_child == c
179
+ string
180
+ }
181
+ end
182
182
 
183
- def terminal(node, seed)
184
- seed + node.left
185
- end
183
+ def terminal(node, seed)
184
+ seed + node.left
185
+ end
186
186
 
187
- def visit_GROUP(node, seed)
188
- visit(node.left, seed << "(".freeze) << ")".freeze
189
- end
187
+ def visit_GROUP(node, seed)
188
+ visit(node.left, seed << "(".freeze) << ")".freeze
189
+ end
190
190
 
191
- INSTANCE = new
191
+ INSTANCE = new
192
192
  end
193
193
 
194
194
  class Dot < FunctionalVisitor # :nodoc:
@@ -1,4 +1,3 @@
1
-
2
1
  module ActionDispatch
3
2
  # Provides callbacks to be executed before and after dispatching the request.
4
3
  class Callbacks
@@ -7,17 +6,6 @@ module ActionDispatch
7
6
  define_callbacks :call
8
7
 
9
8
  class << self
10
- def to_prepare(*args, &block)
11
- ActiveSupport::Reloader.to_prepare(*args, &block)
12
- end
13
-
14
- def to_cleanup(*args, &block)
15
- ActiveSupport::Reloader.to_complete(*args, &block)
16
- end
17
-
18
- deprecate to_prepare: 'use ActiveSupport::Reloader.to_prepare instead',
19
- to_cleanup: 'use ActiveSupport::Reloader.to_complete instead'
20
-
21
9
  def before(*args, &block)
22
10
  set_callback(:call, :before, *args, &block)
23
11
  end
@@ -1,13 +1,13 @@
1
- require 'active_support/core_ext/hash/keys'
2
- require 'active_support/key_generator'
3
- require 'active_support/message_verifier'
4
- require 'active_support/json'
5
- require 'rack/utils'
1
+ require "active_support/core_ext/hash/keys"
2
+ require "active_support/key_generator"
3
+ require "active_support/message_verifier"
4
+ require "active_support/json"
5
+ require "rack/utils"
6
6
 
7
7
  module ActionDispatch
8
8
  class Request
9
9
  def cookie_jar
10
- fetch_header('action_dispatch.cookies'.freeze) do
10
+ fetch_header("action_dispatch.cookies".freeze) do
11
11
  self.cookie_jar = Cookies::CookieJar.build(self, cookies)
12
12
  end
13
13
  end
@@ -20,11 +20,11 @@ module ActionDispatch
20
20
  }
21
21
 
22
22
  def have_cookie_jar?
23
- has_header? 'action_dispatch.cookies'.freeze
23
+ has_header? "action_dispatch.cookies".freeze
24
24
  end
25
25
 
26
26
  def cookie_jar=(jar)
27
- set_header 'action_dispatch.cookies'.freeze, jar
27
+ set_header "action_dispatch.cookies".freeze, jar
28
28
  end
29
29
 
30
30
  def key_generator
@@ -179,7 +179,7 @@ module ActionDispatch
179
179
 
180
180
  # Returns a jar that'll automatically generate a signed representation of cookie value and verify it when reading from
181
181
  # the cookie again. This is useful for creating cookies with values that the user is not supposed to change. If a signed
182
- # cookie was tampered with by the user (or a 3rd party), nil will be returned.
182
+ # cookie was tampered with by the user (or a 3rd party), +nil+ will be returned.
183
183
  #
184
184
  # If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
185
185
  # legacy cookies signed with the old key generator will be transparently upgraded.
@@ -202,7 +202,7 @@ module ActionDispatch
202
202
  end
203
203
 
204
204
  # Returns a jar that'll automatically encrypt cookie values before sending them to the client and will decrypt them for read.
205
- # If the cookie was tampered with by the user (or a 3rd party), nil will be returned.
205
+ # If the cookie was tampered with by the user (or a 3rd party), +nil+ will be returned.
206
206
  #
207
207
  # If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,
208
208
  # legacy cookies signed with the old key generator will be transparently upgraded.
@@ -237,9 +237,9 @@ module ActionDispatch
237
237
 
238
238
  private
239
239
 
240
- def upgrade_legacy_signed_cookies?
241
- request.secret_token.present? && request.secret_key_base.present?
242
- end
240
+ def upgrade_legacy_signed_cookies?
241
+ request.secret_token.present? && request.secret_key_base.present?
242
+ end
243
243
  end
244
244
 
245
245
  # Passing the ActiveSupport::MessageEncryptor::NullSerializer downstream
@@ -332,19 +332,19 @@ module ActionDispatch
332
332
 
333
333
  def update_cookies_from_jar
334
334
  request_jar = @request.cookie_jar.instance_variable_get(:@cookies)
335
- set_cookies = request_jar.reject { |k,_| @delete_cookies.key?(k) }
335
+ set_cookies = request_jar.reject { |k, _| @delete_cookies.key?(k) }
336
336
 
337
337
  @cookies.update set_cookies if set_cookies
338
338
  end
339
339
 
340
340
  def to_header
341
- @cookies.map { |k,v| "#{escape(k)}=#{escape(v)}" }.join '; '
341
+ @cookies.map { |k, v| "#{escape(k)}=#{escape(v)}" }.join "; "
342
342
  end
343
343
 
344
344
  def handle_options(options) #:nodoc:
345
345
  options[:path] ||= "/"
346
346
 
347
- if options[:domain] == :all || options[:domain] == 'all'
347
+ if options[:domain] == :all || options[:domain] == "all"
348
348
  # if there is a provided tld length then we use it otherwise default domain regexp
349
349
  domain_regexp = options[:tld_length] ? /([^.]+\.?){#{options[:tld_length]}}$/ : DOMAIN_REGEXP
350
350
 
@@ -355,7 +355,7 @@ module ActionDispatch
355
355
  end
356
356
  elsif options[:domain].is_a? Array
357
357
  # if host matches one of the supplied domains without a dot in front of it
358
- options[:domain] = options[:domain].find {|domain| request.host.include? domain.sub(/^\./, '') }
358
+ options[:domain] = options[:domain].find { |domain| request.host.include? domain.sub(/^\./, "") }
359
359
  end
360
360
  end
361
361
 
@@ -367,7 +367,7 @@ module ActionDispatch
367
367
  value = options[:value]
368
368
  else
369
369
  value = options
370
- options = { :value => value }
370
+ options = { value: value }
371
371
  end
372
372
 
373
373
  handle_options(options)
@@ -406,7 +406,7 @@ module ActionDispatch
406
406
 
407
407
  # Removes all cookies on the client machine by calling <tt>delete</tt> for each cookie
408
408
  def clear(options = {})
409
- @cookies.each_key{ |k| delete(k, options) }
409
+ @cookies.each_key { |k| delete(k, options) }
410
410
  end
411
411
 
412
412
  def write(headers)
@@ -420,26 +420,26 @@ module ActionDispatch
420
420
 
421
421
  private
422
422
 
423
- def escape(string)
424
- ::Rack::Utils.escape(string)
425
- end
423
+ def escape(string)
424
+ ::Rack::Utils.escape(string)
425
+ end
426
426
 
427
- def make_set_cookie_header(header)
428
- header = @set_cookies.inject(header) { |m, (k, v)|
429
- if write_cookie?(v)
430
- ::Rack::Utils.add_cookie_to_header(m, k, v)
431
- else
432
- m
433
- end
434
- }
435
- @delete_cookies.inject(header) { |m, (k, v)|
436
- ::Rack::Utils.add_remove_cookie_to_header(m, k, v)
437
- }
438
- end
427
+ def make_set_cookie_header(header)
428
+ header = @set_cookies.inject(header) { |m, (k, v)|
429
+ if write_cookie?(v)
430
+ ::Rack::Utils.add_cookie_to_header(m, k, v)
431
+ else
432
+ m
433
+ end
434
+ }
435
+ @delete_cookies.inject(header) { |m, (k, v)|
436
+ ::Rack::Utils.add_remove_cookie_to_header(m, k, v)
437
+ }
438
+ end
439
439
 
440
- def write_cookie?(cookie)
441
- request.ssl? || !cookie[:secure] || always_write_cookie
442
- end
440
+ def write_cookie?(cookie)
441
+ request.ssl? || !cookie[:secure] || always_write_cookie
442
+ end
443
443
  end
444
444
 
445
445
  class AbstractCookieJar # :nodoc:
@@ -528,7 +528,7 @@ module ActionDispatch
528
528
  end
529
529
 
530
530
  def digest
531
- request.cookies_digest || 'SHA1'
531
+ request.cookies_digest || "SHA1"
532
532
  end
533
533
 
534
534
  def key_generator
@@ -572,7 +572,7 @@ module ActionDispatch
572
572
  super
573
573
 
574
574
  if ActiveSupport::LegacyKeyGenerator === key_generator
575
- raise "You didn't set secrets.secret_key_base, which is required for this cookie jar. " +
575
+ raise "You didn't set secrets.secret_key_base, which is required for this cookie jar. " \
576
576
  "Read the upgrade documentation to learn more about this new config option."
577
577
  end
578
578
 
@@ -1,16 +1,16 @@
1
- require 'action_dispatch/http/request'
2
- require 'action_dispatch/middleware/exception_wrapper'
3
- require 'action_dispatch/routing/inspector'
4
- require 'action_view'
5
- require 'action_view/base'
1
+ require "action_dispatch/http/request"
2
+ require "action_dispatch/middleware/exception_wrapper"
3
+ require "action_dispatch/routing/inspector"
4
+ require "action_view"
5
+ require "action_view/base"
6
6
 
7
- require 'pp'
7
+ require "pp"
8
8
 
9
9
  module ActionDispatch
10
10
  # This middleware is responsible for logging exceptions and
11
11
  # showing a debugging page in case the request is local.
12
12
  class DebugExceptions
13
- RESCUES_TEMPLATE_PATH = File.expand_path('../templates', __FILE__)
13
+ RESCUES_TEMPLATE_PATH = File.expand_path("../templates", __FILE__)
14
14
 
15
15
  class DebugView < ActionView::Base
16
16
  def debug_params(params)
@@ -19,7 +19,7 @@ module ActionDispatch
19
19
  clean_params.delete("controller")
20
20
 
21
21
  if clean_params.empty?
22
- 'None'
22
+ "None"
23
23
  else
24
24
  PP.pp(clean_params, "", 200)
25
25
  end
@@ -27,15 +27,25 @@ module ActionDispatch
27
27
 
28
28
  def debug_headers(headers)
29
29
  if headers.present?
30
- headers.inspect.gsub(',', ",\n")
30
+ headers.inspect.gsub(",", ",\n")
31
31
  else
32
- 'None'
32
+ "None"
33
33
  end
34
34
  end
35
35
 
36
36
  def debug_hash(object)
37
37
  object.to_hash.sort_by { |k, _| k.to_s }.map { |k, v| "#{k}: #{v.inspect rescue $!.message}" }.join("\n")
38
38
  end
39
+
40
+ def render(*)
41
+ logger = ActionView::Base.logger
42
+
43
+ if logger && logger.respond_to?(:silence)
44
+ logger.silence { super }
45
+ else
46
+ super
47
+ end
48
+ end
39
49
  end
40
50
 
41
51
  def initialize(app, routes_app = nil, response_format = :default)
@@ -48,7 +58,7 @@ module ActionDispatch
48
58
  request = ActionDispatch::Request.new env
49
59
  _, headers, body = response = @app.call(env)
50
60
 
51
- if headers['X-Cascade'] == 'pass'
61
+ if headers["X-Cascade"] == "pass"
52
62
  body.close if body.respond_to?(:close)
53
63
  raise ActionController::RoutingError, "No route matches [#{env['REQUEST_METHOD']}] #{env['PATH_INFO'].inspect}"
54
64
  end
@@ -61,129 +71,133 @@ module ActionDispatch
61
71
 
62
72
  private
63
73
 
64
- def render_exception(request, exception)
65
- backtrace_cleaner = request.get_header('action_dispatch.backtrace_cleaner')
66
- wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
67
- log_error(request, wrapper)
68
-
69
- if request.get_header('action_dispatch.show_detailed_exceptions')
70
- case @response_format
71
- when :api
72
- render_for_api_application(request, wrapper)
73
- when :default
74
- render_for_default_application(request, wrapper)
74
+ def render_exception(request, exception)
75
+ backtrace_cleaner = request.get_header("action_dispatch.backtrace_cleaner")
76
+ wrapper = ExceptionWrapper.new(backtrace_cleaner, exception)
77
+ log_error(request, wrapper)
78
+
79
+ if request.get_header("action_dispatch.show_detailed_exceptions")
80
+ content_type = request.formats.first
81
+
82
+ if api_request?(content_type)
83
+ render_for_api_request(content_type, wrapper)
84
+ else
85
+ render_for_browser_request(request, wrapper)
86
+ end
87
+ else
88
+ raise exception
75
89
  end
76
- else
77
- raise exception
78
90
  end
79
- end
80
91
 
81
- def render_for_default_application(request, wrapper)
82
- template = create_template(request, wrapper)
83
- file = "rescues/#{wrapper.rescue_template}"
92
+ def render_for_browser_request(request, wrapper)
93
+ template = create_template(request, wrapper)
94
+ file = "rescues/#{wrapper.rescue_template}"
84
95
 
85
- if request.xhr?
86
- body = template.render(template: file, layout: false, formats: [:text])
87
- format = "text/plain"
88
- else
89
- body = template.render(template: file, layout: 'rescues/layout')
90
- format = "text/html"
96
+ if request.xhr?
97
+ body = template.render(template: file, layout: false, formats: [:text])
98
+ format = "text/plain"
99
+ else
100
+ body = template.render(template: file, layout: "rescues/layout")
101
+ format = "text/html"
102
+ end
103
+ render(wrapper.status_code, body, format)
91
104
  end
92
- render(wrapper.status_code, body, format)
93
- end
94
-
95
- def render_for_api_application(request, wrapper)
96
- body = {
97
- status: wrapper.status_code,
98
- error: Rack::Utils::HTTP_STATUS_CODES.fetch(
99
- wrapper.status_code,
100
- Rack::Utils::HTTP_STATUS_CODES[500]
101
- ),
102
- exception: wrapper.exception.inspect,
103
- traces: wrapper.traces
104
- }
105
-
106
- content_type = request.formats.first
107
- to_format = "to_#{content_type.to_sym}"
108
-
109
- if content_type && body.respond_to?(to_format)
110
- formatted_body = body.public_send(to_format)
111
- format = content_type
112
- else
113
- formatted_body = body.to_json
114
- format = Mime[:json]
115
- end
116
-
117
- render(wrapper.status_code, formatted_body, format)
118
- end
119
105
 
120
- def create_template(request, wrapper)
121
- traces = wrapper.traces
106
+ def render_for_api_request(content_type, wrapper)
107
+ body = {
108
+ status: wrapper.status_code,
109
+ error: Rack::Utils::HTTP_STATUS_CODES.fetch(
110
+ wrapper.status_code,
111
+ Rack::Utils::HTTP_STATUS_CODES[500]
112
+ ),
113
+ exception: wrapper.exception.inspect,
114
+ traces: wrapper.traces
115
+ }
116
+
117
+ to_format = "to_#{content_type.to_sym}"
118
+
119
+ if content_type && body.respond_to?(to_format)
120
+ formatted_body = body.public_send(to_format)
121
+ format = content_type
122
+ else
123
+ formatted_body = body.to_json
124
+ format = Mime[:json]
125
+ end
122
126
 
123
- trace_to_show = 'Application Trace'
124
- if traces[trace_to_show].empty? && wrapper.rescue_template != 'routing_error'
125
- trace_to_show = 'Full Trace'
127
+ render(wrapper.status_code, formatted_body, format)
126
128
  end
127
129
 
128
- if source_to_show = traces[trace_to_show].first
129
- source_to_show_id = source_to_show[:id]
130
+ def create_template(request, wrapper)
131
+ traces = wrapper.traces
132
+
133
+ trace_to_show = "Application Trace"
134
+ if traces[trace_to_show].empty? && wrapper.rescue_template != "routing_error"
135
+ trace_to_show = "Full Trace"
136
+ end
137
+
138
+ if source_to_show = traces[trace_to_show].first
139
+ source_to_show_id = source_to_show[:id]
140
+ end
141
+
142
+ DebugView.new([RESCUES_TEMPLATE_PATH],
143
+ request: request,
144
+ exception: wrapper.exception,
145
+ traces: traces,
146
+ show_source_idx: source_to_show_id,
147
+ trace_to_show: trace_to_show,
148
+ routes_inspector: routes_inspector(wrapper.exception),
149
+ source_extracts: wrapper.source_extracts,
150
+ line_number: wrapper.line_number,
151
+ file: wrapper.file
152
+ )
130
153
  end
131
154
 
132
- DebugView.new([RESCUES_TEMPLATE_PATH],
133
- request: request,
134
- exception: wrapper.exception,
135
- traces: traces,
136
- show_source_idx: source_to_show_id,
137
- trace_to_show: trace_to_show,
138
- routes_inspector: routes_inspector(wrapper.exception),
139
- source_extracts: wrapper.source_extracts,
140
- line_number: wrapper.line_number,
141
- file: wrapper.file
142
- )
143
- end
155
+ def render(status, body, format)
156
+ [status, { "Content-Type" => "#{format}; charset=#{Response.default_charset}", "Content-Length" => body.bytesize.to_s }, [body]]
157
+ end
144
158
 
145
- def render(status, body, format)
146
- [status, {'Content-Type' => "#{format}; charset=#{Response.default_charset}", 'Content-Length' => body.bytesize.to_s}, [body]]
147
- end
159
+ def log_error(request, wrapper)
160
+ logger = logger(request)
161
+ return unless logger
148
162
 
149
- def log_error(request, wrapper)
150
- logger = logger(request)
151
- return unless logger
163
+ exception = wrapper.exception
152
164
 
153
- exception = wrapper.exception
165
+ trace = wrapper.application_trace
166
+ trace = wrapper.framework_trace if trace.empty?
154
167
 
155
- trace = wrapper.application_trace
156
- trace = wrapper.framework_trace if trace.empty?
168
+ ActiveSupport::Deprecation.silence do
169
+ logger.fatal " "
170
+ logger.fatal "#{exception.class} (#{exception.message}):"
171
+ log_array logger, exception.annoted_source_code if exception.respond_to?(:annoted_source_code)
172
+ logger.fatal " "
173
+ log_array logger, trace
174
+ end
175
+ end
157
176
 
158
- ActiveSupport::Deprecation.silence do
159
- logger.fatal " "
160
- logger.fatal "#{exception.class} (#{exception.message}):"
161
- log_array logger, exception.annoted_source_code if exception.respond_to?(:annoted_source_code)
162
- logger.fatal " "
163
- log_array logger, trace
177
+ def log_array(logger, array)
178
+ if logger.formatter && logger.formatter.respond_to?(:tags_text)
179
+ logger.fatal array.join("\n#{logger.formatter.tags_text}")
180
+ else
181
+ logger.fatal array.join("\n")
182
+ end
164
183
  end
165
- end
166
184
 
167
- def log_array(logger, array)
168
- if logger.formatter && logger.formatter.respond_to?(:tags_text)
169
- logger.fatal array.join("\n#{logger.formatter.tags_text}")
170
- else
171
- logger.fatal array.join("\n")
185
+ def logger(request)
186
+ request.logger || ActionView::Base.logger || stderr_logger
172
187
  end
173
- end
174
188
 
175
- def logger(request)
176
- request.logger || ActionView::Base.logger || stderr_logger
177
- end
189
+ def stderr_logger
190
+ @stderr_logger ||= ActiveSupport::Logger.new($stderr)
191
+ end
178
192
 
179
- def stderr_logger
180
- @stderr_logger ||= ActiveSupport::Logger.new($stderr)
181
- end
193
+ def routes_inspector(exception)
194
+ if @routes_app.respond_to?(:routes) && (exception.is_a?(ActionController::RoutingError) || exception.is_a?(ActionView::Template::Error))
195
+ ActionDispatch::Routing::RoutesInspector.new(@routes_app.routes.routes)
196
+ end
197
+ end
182
198
 
183
- def routes_inspector(exception)
184
- if @routes_app.respond_to?(:routes) && (exception.is_a?(ActionController::RoutingError) || exception.is_a?(ActionView::Template::Error))
185
- ActionDispatch::Routing::RoutesInspector.new(@routes_app.routes.routes)
199
+ def api_request?(content_type)
200
+ @response_format == :api && !content_type.html?
186
201
  end
187
- end
188
202
  end
189
203
  end