actionpack 3.0.0.beta3 → 3.0.0.beta4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of actionpack might be problematic. Click here for more details.
- data/CHANGELOG +19 -0
- data/lib/abstract_controller.rb +1 -1
- data/lib/abstract_controller/asset_paths.rb +9 -0
- data/lib/abstract_controller/base.rb +5 -13
- data/lib/abstract_controller/callbacks.rb +1 -1
- data/lib/abstract_controller/helpers.rb +0 -1
- data/lib/abstract_controller/layouts.rb +3 -3
- data/lib/abstract_controller/logger.rb +1 -1
- data/lib/abstract_controller/rendering.rb +1 -0
- data/lib/action_controller/base.rb +5 -1
- data/lib/action_controller/caching.rb +2 -3
- data/lib/action_controller/caching/actions.rb +1 -1
- data/lib/action_controller/caching/fragments.rb +1 -1
- data/lib/action_controller/caching/pages.rb +8 -8
- data/lib/action_controller/caching/sweeping.rb +1 -0
- data/lib/action_controller/deprecated/base.rb +10 -36
- data/lib/action_controller/metal.rb +45 -3
- data/lib/action_controller/metal/compatibility.rb +2 -2
- data/lib/action_controller/metal/helpers.rb +3 -3
- data/lib/action_controller/metal/http_authentication.rb +158 -0
- data/lib/action_controller/metal/instrumentation.rb +5 -5
- data/lib/action_controller/metal/rack_delegation.rb +4 -4
- data/lib/action_controller/metal/renderers.rb +3 -3
- data/lib/action_controller/metal/request_forgery_protection.rb +45 -74
- data/lib/action_controller/metal/responder.rb +1 -1
- data/lib/action_controller/metal/url_for.rb +8 -0
- data/lib/action_controller/railtie.rb +26 -39
- data/lib/action_controller/test_case.rb +147 -135
- data/lib/action_controller/vendor/html-scanner/html/tokenizer.rb +1 -0
- data/lib/action_dispatch.rb +0 -1
- data/lib/action_dispatch/http/parameters.rb +2 -1
- data/lib/action_dispatch/http/request.rb +19 -7
- data/lib/action_dispatch/http/response.rb +3 -33
- data/lib/action_dispatch/middleware/cookies.rb +44 -10
- data/lib/action_dispatch/middleware/flash.rb +11 -1
- data/lib/action_dispatch/middleware/params_parser.rb +3 -1
- data/lib/action_dispatch/middleware/session/abstract_store.rb +47 -83
- data/lib/action_dispatch/middleware/session/cookie_store.rb +19 -165
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +2 -2
- data/lib/action_dispatch/middleware/show_exceptions.rb +18 -12
- data/lib/action_dispatch/middleware/stack.rb +17 -67
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +1 -1
- data/lib/action_dispatch/railtie.rb +0 -2
- data/lib/action_dispatch/routing/deprecated_mapper.rb +1 -0
- data/lib/action_dispatch/routing/mapper.rb +89 -23
- data/lib/action_dispatch/routing/route_set.rb +22 -16
- data/lib/action_dispatch/routing/url_for.rb +1 -1
- data/lib/action_dispatch/testing/assertions/routing.rb +1 -0
- data/lib/action_dispatch/testing/assertions/selector.rb +11 -7
- data/lib/action_dispatch/testing/test_process.rb +3 -2
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view.rb +5 -1
- data/lib/action_view/base.rb +10 -4
- data/lib/action_view/helpers/active_model_helper.rb +1 -8
- data/lib/action_view/helpers/asset_tag_helper.rb +7 -4
- data/lib/action_view/helpers/cache_helper.rb +14 -14
- data/lib/action_view/helpers/capture_helper.rb +25 -6
- data/lib/action_view/helpers/date_helper.rb +33 -44
- data/lib/action_view/helpers/form_helper.rb +47 -27
- data/lib/action_view/helpers/form_options_helper.rb +26 -3
- data/lib/action_view/helpers/form_tag_helper.rb +8 -4
- data/lib/action_view/helpers/number_helper.rb +5 -2
- data/lib/action_view/helpers/prototype_helper.rb +1 -1
- data/lib/action_view/helpers/tag_helper.rb +1 -1
- data/lib/action_view/helpers/text_helper.rb +55 -46
- data/lib/action_view/helpers/translation_helper.rb +19 -8
- data/lib/action_view/helpers/url_helper.rb +2 -4
- data/lib/action_view/locale/en.yml +14 -14
- data/lib/action_view/lookup_context.rb +52 -22
- data/lib/action_view/paths.rb +1 -0
- data/lib/action_view/render/layouts.rb +3 -12
- data/lib/action_view/render/partials.rb +21 -10
- data/lib/action_view/render/rendering.rb +1 -1
- data/lib/action_view/template.rb +172 -26
- data/lib/action_view/template/error.rb +25 -27
- data/lib/action_view/template/handlers.rb +1 -1
- data/lib/action_view/template/handlers/erb.rb +92 -45
- data/lib/action_view/template/resolver.rb +4 -1
- data/lib/action_view/test_case.rb +105 -72
- data/lib/action_view/testing/resolvers.rb +43 -0
- metadata +62 -20
- data/lib/abstract_controller/assigns.rb +0 -21
- data/lib/action_dispatch/middleware/cascade.rb +0 -29
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'rack/session/abstract/id'
|
2
2
|
require 'active_support/core_ext/object/blank'
|
3
|
+
require 'active_support/core_ext/object/to_query'
|
3
4
|
|
4
5
|
module ActionController
|
5
6
|
module TemplateAssertions
|
@@ -15,12 +16,12 @@ module ActionController
|
|
15
16
|
@templates = Hash.new(0)
|
16
17
|
@layouts = Hash.new(0)
|
17
18
|
|
18
|
-
ActiveSupport::Notifications.subscribe("action_view
|
19
|
+
ActiveSupport::Notifications.subscribe("render_template.action_view") do |name, start, finish, id, payload|
|
19
20
|
path = payload[:layout]
|
20
21
|
@layouts[path] += 1
|
21
22
|
end
|
22
23
|
|
23
|
-
ActiveSupport::Notifications.subscribe("action_view
|
24
|
+
ActiveSupport::Notifications.subscribe("!render_template.action_view") do |name, start, finish, id, payload|
|
24
25
|
path = payload[:virtual_path]
|
25
26
|
next unless path
|
26
27
|
partial = path =~ /^.*\/_[^\/]*$/
|
@@ -35,7 +36,8 @@ module ActionController
|
|
35
36
|
end
|
36
37
|
|
37
38
|
def teardown_subscriptions
|
38
|
-
ActiveSupport::Notifications.unsubscribe("action_view
|
39
|
+
ActiveSupport::Notifications.unsubscribe("render_template.action_view")
|
40
|
+
ActiveSupport::Notifications.unsubscribe("!render_template.action_view")
|
39
41
|
end
|
40
42
|
|
41
43
|
# Asserts that the request was rendered with the appropriate template file or partials
|
@@ -55,7 +57,8 @@ module ActionController
|
|
55
57
|
validate_request!
|
56
58
|
|
57
59
|
case options
|
58
|
-
when NilClass, String
|
60
|
+
when NilClass, String, Symbol
|
61
|
+
options = options.to_s if Symbol === options
|
59
62
|
rendered = @templates
|
60
63
|
msg = build_message(message,
|
61
64
|
"expecting <?> but rendering with <?>",
|
@@ -136,14 +139,16 @@ module ActionController
|
|
136
139
|
end
|
137
140
|
end
|
138
141
|
|
139
|
-
params
|
142
|
+
# Clear the combined params hash in case it was already referenced.
|
143
|
+
@env.delete("action_dispatch.request.parameters")
|
140
144
|
|
145
|
+
params = self.request_parameters.dup
|
141
146
|
%w(controller action only_path).each do |k|
|
142
147
|
params.delete(k)
|
143
148
|
params.delete(k.to_sym)
|
144
149
|
end
|
145
|
-
|
146
150
|
data = params.to_query
|
151
|
+
|
147
152
|
@env['CONTENT_LENGTH'] = data.length.to_s
|
148
153
|
@env['rack.input'] = StringIO.new(data)
|
149
154
|
end
|
@@ -152,6 +157,8 @@ module ActionController
|
|
152
157
|
@formats = nil
|
153
158
|
@env.delete_if { |k, v| k =~ /^(action_dispatch|rack)\.request/ }
|
154
159
|
@env.delete_if { |k, v| k =~ /^action_dispatch\.rescue/ }
|
160
|
+
@method = @request_method = nil
|
161
|
+
@fullpath = @ip = @remote_ip = nil
|
155
162
|
@env['action_dispatch.request.query_parameters'] = {}
|
156
163
|
end
|
157
164
|
end
|
@@ -164,9 +171,7 @@ module ActionController
|
|
164
171
|
@block = nil
|
165
172
|
@length = 0
|
166
173
|
@body = []
|
167
|
-
@charset = nil
|
168
|
-
@content_type = nil
|
169
|
-
|
174
|
+
@charset = @content_type = nil
|
170
175
|
@request = @template = nil
|
171
176
|
end
|
172
177
|
end
|
@@ -281,165 +286,143 @@ module ActionController
|
|
281
286
|
#
|
282
287
|
# assert_redirected_to page_url(:title => 'foo')
|
283
288
|
class TestCase < ActiveSupport::TestCase
|
284
|
-
|
285
|
-
|
289
|
+
module Behavior
|
290
|
+
extend ActiveSupport::Concern
|
291
|
+
include ActionDispatch::TestProcess
|
286
292
|
|
287
|
-
|
293
|
+
attr_reader :response, :request
|
288
294
|
|
289
|
-
|
290
|
-
def get(action, parameters = nil, session = nil, flash = nil)
|
291
|
-
process(action, parameters, session, flash, "GET")
|
292
|
-
end
|
295
|
+
module ClassMethods
|
293
296
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
297
|
+
# Sets the controller class name. Useful if the name can't be inferred from test class.
|
298
|
+
# Expects +controller_class+ as a constant. Example: <tt>tests WidgetController</tt>.
|
299
|
+
def tests(controller_class)
|
300
|
+
self.controller_class = controller_class
|
301
|
+
end
|
302
|
+
|
303
|
+
def controller_class=(new_class)
|
304
|
+
prepare_controller_class(new_class) if new_class
|
305
|
+
write_inheritable_attribute(:controller_class, new_class)
|
306
|
+
end
|
298
307
|
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
|
308
|
+
def controller_class
|
309
|
+
if current_controller_class = read_inheritable_attribute(:controller_class)
|
310
|
+
current_controller_class
|
311
|
+
else
|
312
|
+
self.controller_class = determine_default_controller_class(name)
|
313
|
+
end
|
314
|
+
end
|
303
315
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
316
|
+
def determine_default_controller_class(name)
|
317
|
+
name.sub(/Test$/, '').constantize
|
318
|
+
rescue NameError
|
319
|
+
nil
|
320
|
+
end
|
308
321
|
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
end
|
322
|
+
def prepare_controller_class(new_class)
|
323
|
+
new_class.send :include, ActionController::TestCase::RaiseActionExceptions
|
324
|
+
end
|
313
325
|
|
314
|
-
def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
|
315
|
-
@request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
|
316
|
-
@request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
|
317
|
-
returning __send__(request_method, action, parameters, session, flash) do
|
318
|
-
@request.env.delete 'HTTP_X_REQUESTED_WITH'
|
319
|
-
@request.env.delete 'HTTP_ACCEPT'
|
320
326
|
end
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
# Sanity check for required instance variables so we can give an
|
326
|
-
# understandable error message.
|
327
|
-
%w(@routes @controller @request @response).each do |iv_name|
|
328
|
-
if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil?
|
329
|
-
raise "#{iv_name} is nil: make sure you set it in your test's setup method."
|
330
|
-
end
|
327
|
+
|
328
|
+
# Executes a request simulating GET HTTP method and set/volley the response
|
329
|
+
def get(action, parameters = nil, session = nil, flash = nil)
|
330
|
+
process(action, parameters, session, flash, "GET")
|
331
331
|
end
|
332
332
|
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
@controller.params = nil
|
338
|
-
|
339
|
-
@html_document = nil
|
340
|
-
@request.env['REQUEST_METHOD'] = http_method
|
341
|
-
|
342
|
-
parameters ||= {}
|
343
|
-
@request.assign_parameters(@routes, @controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters)
|
344
|
-
|
345
|
-
@request.session = ActionController::TestSession.new(session) unless session.nil?
|
346
|
-
@request.session["flash"] = @request.flash.update(flash || {})
|
347
|
-
@request.session["flash"].sweep
|
348
|
-
|
349
|
-
@controller.request = @request
|
350
|
-
@controller.params.merge!(parameters)
|
351
|
-
build_request_uri(action, parameters)
|
352
|
-
Base.class_eval { include Testing }
|
353
|
-
@controller.process_with_new_base_test(@request, @response)
|
354
|
-
@request.session.delete('flash') if @request.session['flash'].blank?
|
355
|
-
@response
|
356
|
-
end
|
333
|
+
# Executes a request simulating POST HTTP method and set/volley the response
|
334
|
+
def post(action, parameters = nil, session = nil, flash = nil)
|
335
|
+
process(action, parameters, session, flash, "POST")
|
336
|
+
end
|
357
337
|
|
358
|
-
|
338
|
+
# Executes a request simulating PUT HTTP method and set/volley the response
|
339
|
+
def put(action, parameters = nil, session = nil, flash = nil)
|
340
|
+
process(action, parameters, session, flash, "PUT")
|
341
|
+
end
|
359
342
|
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
# than 0.0.0.0.
|
364
|
-
#
|
365
|
-
# The exception is stored in the exception accessor for further inspection.
|
366
|
-
module RaiseActionExceptions
|
367
|
-
def self.included(base)
|
368
|
-
base.class_eval do
|
369
|
-
attr_accessor :exception
|
370
|
-
protected :exception, :exception=
|
371
|
-
end
|
343
|
+
# Executes a request simulating DELETE HTTP method and set/volley the response
|
344
|
+
def delete(action, parameters = nil, session = nil, flash = nil)
|
345
|
+
process(action, parameters, session, flash, "DELETE")
|
372
346
|
end
|
373
347
|
|
374
|
-
|
375
|
-
|
376
|
-
|
348
|
+
# Executes a request simulating HEAD HTTP method and set/volley the response
|
349
|
+
def head(action, parameters = nil, session = nil, flash = nil)
|
350
|
+
process(action, parameters, session, flash, "HEAD")
|
351
|
+
end
|
377
352
|
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
353
|
+
def xml_http_request(request_method, action, parameters = nil, session = nil, flash = nil)
|
354
|
+
@request.env['HTTP_X_REQUESTED_WITH'] = 'XMLHttpRequest'
|
355
|
+
@request.env['HTTP_ACCEPT'] ||= [Mime::JS, Mime::HTML, Mime::XML, 'text/xml', Mime::ALL].join(', ')
|
356
|
+
returning __send__(request_method, action, parameters, session, flash) do
|
357
|
+
@request.env.delete 'HTTP_X_REQUESTED_WITH'
|
358
|
+
@request.env.delete 'HTTP_ACCEPT'
|
359
|
+
end
|
360
|
+
end
|
361
|
+
alias xhr :xml_http_request
|
362
|
+
|
363
|
+
def process(action, parameters = nil, session = nil, flash = nil, http_method = 'GET')
|
364
|
+
# Sanity check for required instance variables so we can give an
|
365
|
+
# understandable error message.
|
366
|
+
%w(@routes @controller @request @response).each do |iv_name|
|
367
|
+
if !(instance_variable_names.include?(iv_name) || instance_variable_names.include?(iv_name.to_sym)) || instance_variable_get(iv_name).nil?
|
368
|
+
raise "#{iv_name} is nil: make sure you set it in your test's setup method."
|
382
369
|
end
|
383
370
|
end
|
384
|
-
end
|
385
371
|
|
386
|
-
|
372
|
+
@request.recycle!
|
373
|
+
@response.recycle!
|
374
|
+
@controller.response_body = nil
|
375
|
+
@controller.formats = nil
|
376
|
+
@controller.params = nil
|
387
377
|
|
388
|
-
|
378
|
+
@html_document = nil
|
379
|
+
@request.env['REQUEST_METHOD'] = http_method
|
389
380
|
|
390
|
-
|
391
|
-
|
392
|
-
# Expects +controller_class+ as a constant. Example: <tt>tests WidgetController</tt>.
|
393
|
-
def tests(controller_class)
|
394
|
-
self.controller_class = controller_class
|
395
|
-
end
|
381
|
+
parameters ||= {}
|
382
|
+
@request.assign_parameters(@routes, @controller.class.name.underscore.sub(/_controller$/, ''), action.to_s, parameters)
|
396
383
|
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
end
|
384
|
+
@request.session = ActionController::TestSession.new(session) unless session.nil?
|
385
|
+
@request.session["flash"] = @request.flash.update(flash || {})
|
386
|
+
@request.session["flash"].sweep
|
401
387
|
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
388
|
+
@controller.request = @request
|
389
|
+
@controller.params.merge!(parameters)
|
390
|
+
build_request_uri(action, parameters)
|
391
|
+
Base.class_eval { include Testing }
|
392
|
+
@controller.process_with_new_base_test(@request, @response)
|
393
|
+
@request.session.delete('flash') if @request.session['flash'].blank?
|
394
|
+
@response
|
408
395
|
end
|
409
396
|
|
410
|
-
def
|
411
|
-
|
412
|
-
|
413
|
-
nil
|
414
|
-
end
|
397
|
+
def setup_controller_request_and_response
|
398
|
+
@request = TestRequest.new
|
399
|
+
@response = TestResponse.new
|
415
400
|
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
end
|
401
|
+
if klass = self.class.controller_class
|
402
|
+
@controller ||= klass.new rescue nil
|
403
|
+
end
|
420
404
|
|
421
|
-
|
422
|
-
@request = TestRequest.new
|
423
|
-
@response = TestResponse.new
|
405
|
+
@request.env.delete('PATH_INFO')
|
424
406
|
|
425
|
-
|
426
|
-
|
407
|
+
if @controller
|
408
|
+
@controller.request = @request
|
409
|
+
@controller.params = {}
|
410
|
+
end
|
427
411
|
end
|
428
412
|
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
@controller.request = @request
|
433
|
-
@controller.params = {}
|
413
|
+
# Cause the action to be rescued according to the regular rules for rescue_action when the visitor is not local
|
414
|
+
def rescue_action_in_public!
|
415
|
+
@request.remote_addr = '208.77.188.166' # example.com
|
434
416
|
end
|
435
|
-
end
|
436
417
|
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
418
|
+
included do
|
419
|
+
include ActionController::TemplateAssertions
|
420
|
+
include ActionDispatch::Assertions
|
421
|
+
setup :setup_controller_request_and_response
|
422
|
+
end
|
441
423
|
|
442
424
|
private
|
425
|
+
|
443
426
|
def build_request_uri(action, parameters)
|
444
427
|
unless @request.env["PATH_INFO"]
|
445
428
|
options = @controller.__send__(:url_options).merge(parameters)
|
@@ -457,4 +440,33 @@ module ActionController
|
|
457
440
|
end
|
458
441
|
end
|
459
442
|
end
|
443
|
+
|
444
|
+
# When the request.remote_addr remains the default for testing, which is 0.0.0.0, the exception is simply raised inline
|
445
|
+
# (bystepping the regular exception handling from rescue_action). If the request.remote_addr is anything else, the regular
|
446
|
+
# rescue_action process takes place. This means you can test your rescue_action code by setting remote_addr to something else
|
447
|
+
# than 0.0.0.0.
|
448
|
+
#
|
449
|
+
# The exception is stored in the exception accessor for further inspection.
|
450
|
+
module RaiseActionExceptions
|
451
|
+
def self.included(base)
|
452
|
+
base.class_eval do
|
453
|
+
attr_accessor :exception
|
454
|
+
protected :exception, :exception=
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
protected
|
459
|
+
def rescue_action_without_handler(e)
|
460
|
+
self.exception = e
|
461
|
+
|
462
|
+
if request.remote_addr == "0.0.0.0"
|
463
|
+
raise(e)
|
464
|
+
else
|
465
|
+
super(e)
|
466
|
+
end
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
include Behavior
|
471
|
+
end
|
460
472
|
end
|
data/lib/action_dispatch.rb
CHANGED
@@ -52,9 +52,11 @@ module ActionDispatch
|
|
52
52
|
# the application should use), this \method returns the overridden
|
53
53
|
# value, not the original.
|
54
54
|
def request_method
|
55
|
-
|
56
|
-
|
57
|
-
|
55
|
+
@request_method ||= begin
|
56
|
+
method = env["REQUEST_METHOD"]
|
57
|
+
HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
|
58
|
+
method
|
59
|
+
end
|
58
60
|
end
|
59
61
|
|
60
62
|
# Returns a symbol form of the #request_method
|
@@ -66,9 +68,11 @@ module ActionDispatch
|
|
66
68
|
# even if it was overridden by middleware. See #request_method for
|
67
69
|
# more information.
|
68
70
|
def method
|
69
|
-
method
|
70
|
-
|
71
|
-
|
71
|
+
@method ||= begin
|
72
|
+
method = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD']
|
73
|
+
HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
|
74
|
+
method
|
75
|
+
end
|
72
76
|
end
|
73
77
|
|
74
78
|
# Returns a symbol form of the #method
|
@@ -113,6 +117,10 @@ module ActionDispatch
|
|
113
117
|
Http::Headers.new(@env)
|
114
118
|
end
|
115
119
|
|
120
|
+
def fullpath
|
121
|
+
@fullpath ||= super
|
122
|
+
end
|
123
|
+
|
116
124
|
def forgery_whitelisted?
|
117
125
|
get? || xhr? || content_mime_type.nil? || !content_mime_type.verify_request?
|
118
126
|
end
|
@@ -134,6 +142,10 @@ module ActionDispatch
|
|
134
142
|
end
|
135
143
|
alias :xhr? :xml_http_request?
|
136
144
|
|
145
|
+
def ip
|
146
|
+
@ip ||= super
|
147
|
+
end
|
148
|
+
|
137
149
|
# Which IP addresses are "trusted proxies" that can be stripped from
|
138
150
|
# the right-hand-side of X-Forwarded-For
|
139
151
|
TRUSTED_PROXIES = /^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i
|
@@ -145,7 +157,7 @@ module ActionDispatch
|
|
145
157
|
# delimited list in the case of multiple chained proxies; the last
|
146
158
|
# address which is not trusted is the originating IP.
|
147
159
|
def remote_ip
|
148
|
-
(@env["action_dispatch.remote_ip"] || ip).to_s
|
160
|
+
@remote_ip ||= (@env["action_dispatch.remote_ip"] || ip).to_s
|
149
161
|
end
|
150
162
|
|
151
163
|
# Returns the lowercase name of the HTTP server software.
|