actionpack 3.0.0.beta → 3.0.0.beta2
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.
- data/CHANGELOG +291 -260
- data/lib/abstract_controller.rb +5 -2
- data/lib/abstract_controller/assigns.rb +21 -0
- data/lib/abstract_controller/base.rb +13 -5
- data/lib/abstract_controller/collector.rb +2 -0
- data/lib/abstract_controller/helpers.rb +4 -14
- data/lib/abstract_controller/layouts.rb +50 -99
- data/lib/abstract_controller/logger.rb +2 -2
- data/lib/abstract_controller/rendering.rb +105 -173
- data/lib/abstract_controller/view_paths.rb +69 -0
- data/lib/action_controller.rb +1 -2
- data/lib/action_controller/base.rb +10 -32
- data/lib/action_controller/caching.rb +19 -18
- data/lib/action_controller/caching/actions.rb +17 -11
- data/lib/action_controller/caching/fragments.rb +5 -17
- data/lib/action_controller/caching/pages.rb +24 -24
- data/lib/action_controller/caching/sweeping.rb +1 -3
- data/lib/action_controller/deprecated.rb +0 -2
- data/lib/action_controller/deprecated/base.rb +143 -0
- data/lib/action_controller/metal.rb +29 -26
- data/lib/action_controller/metal/compatibility.rb +18 -87
- data/lib/action_controller/metal/cookies.rb +0 -1
- data/lib/action_controller/metal/head.rb +1 -0
- data/lib/action_controller/metal/helpers.rb +2 -2
- data/lib/action_controller/metal/hide_actions.rb +4 -6
- data/lib/action_controller/metal/http_authentication.rb +18 -33
- data/lib/action_controller/metal/implicit_render.rb +21 -0
- data/lib/action_controller/metal/instrumentation.rb +1 -1
- data/lib/action_controller/metal/mime_responds.rb +2 -1
- data/lib/action_controller/metal/rack_delegation.rb +3 -8
- data/lib/action_controller/metal/redirecting.rb +2 -1
- data/lib/action_controller/metal/renderers.rb +4 -2
- data/lib/action_controller/metal/rendering.rb +31 -44
- data/lib/action_controller/metal/request_forgery_protection.rb +41 -4
- data/lib/action_controller/metal/responder.rb +2 -0
- data/lib/action_controller/metal/session_management.rb +0 -36
- data/lib/action_controller/metal/streaming.rb +20 -47
- data/lib/action_controller/metal/testing.rb +0 -1
- data/lib/action_controller/metal/url_for.rb +11 -148
- data/lib/action_controller/middleware.rb +2 -1
- data/lib/action_controller/polymorphic_routes.rb +1 -2
- data/lib/action_controller/railtie.rb +63 -10
- data/lib/action_controller/railties/{subscriber.rb → log_subscriber.rb} +5 -12
- data/lib/action_controller/railties/url_helpers.rb +14 -0
- data/lib/action_controller/record_identifier.rb +20 -1
- data/lib/action_controller/test_case.rb +123 -12
- data/lib/action_dispatch.rb +1 -0
- data/lib/action_dispatch/http/cache.rb +20 -3
- data/lib/action_dispatch/http/filter_parameters.rb +40 -25
- data/lib/action_dispatch/http/mime_negotiation.rb +6 -17
- data/lib/action_dispatch/http/mime_type.rb +2 -7
- data/lib/action_dispatch/http/request.rb +12 -33
- data/lib/action_dispatch/http/response.rb +35 -15
- data/lib/action_dispatch/http/upload.rb +2 -0
- data/lib/action_dispatch/http/url.rb +5 -32
- data/lib/action_dispatch/middleware/callbacks.rb +1 -1
- data/lib/action_dispatch/middleware/cookies.rb +4 -3
- data/lib/action_dispatch/middleware/params_parser.rb +4 -3
- data/lib/action_dispatch/middleware/remote_ip.rb +51 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +1 -0
- data/lib/action_dispatch/middleware/session/cookie_store.rb +6 -8
- data/lib/action_dispatch/middleware/show_exceptions.rb +0 -14
- data/lib/action_dispatch/middleware/stack.rb +6 -2
- data/lib/action_dispatch/railtie.rb +3 -1
- data/lib/action_dispatch/routing.rb +2 -0
- data/lib/action_dispatch/routing/deprecated_mapper.rb +35 -7
- data/lib/action_dispatch/routing/mapper.rb +134 -48
- data/lib/action_dispatch/routing/route.rb +2 -2
- data/lib/action_dispatch/routing/route_set.rb +217 -158
- data/lib/action_dispatch/routing/url_for.rb +139 -0
- data/lib/action_dispatch/testing/assertions/response.rb +14 -61
- data/lib/action_dispatch/testing/assertions/routing.rb +25 -14
- data/lib/action_dispatch/testing/integration.rb +32 -50
- data/lib/action_dispatch/testing/performance_test.rb +3 -1
- data/lib/action_dispatch/testing/test_process.rb +2 -0
- data/lib/action_dispatch/testing/test_request.rb +2 -0
- data/lib/action_pack/version.rb +4 -3
- data/lib/action_view.rb +11 -6
- data/lib/action_view/base.rb +33 -121
- data/lib/action_view/context.rb +0 -2
- data/lib/action_view/helpers.rb +26 -23
- data/lib/action_view/helpers/active_model_helper.rb +28 -18
- data/lib/action_view/helpers/asset_tag_helper.rb +109 -54
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/cache_helper.rb +22 -1
- data/lib/action_view/helpers/capture_helper.rb +22 -22
- data/lib/action_view/helpers/date_helper.rb +6 -5
- data/lib/action_view/helpers/form_helper.rb +78 -63
- data/lib/action_view/helpers/form_options_helper.rb +6 -4
- data/lib/action_view/helpers/form_tag_helper.rb +26 -15
- data/lib/action_view/helpers/javascript_helper.rb +90 -10
- data/lib/action_view/helpers/number_helper.rb +315 -118
- data/lib/action_view/helpers/prototype_helper.rb +19 -46
- data/lib/action_view/helpers/record_tag_helper.rb +4 -4
- data/lib/action_view/helpers/tag_helper.rb +7 -24
- data/lib/action_view/helpers/text_helper.rb +8 -7
- data/lib/action_view/helpers/translation_helper.rb +7 -5
- data/lib/action_view/helpers/url_helper.rb +19 -16
- data/lib/action_view/locale/en.yml +45 -6
- data/lib/action_view/lookup_context.rb +190 -0
- data/lib/action_view/paths.rb +22 -63
- data/lib/action_view/railtie.rb +14 -4
- data/lib/action_view/railties/{subscriber.rb → log_subscriber.rb} +1 -1
- data/lib/action_view/render/layouts.rb +73 -0
- data/lib/action_view/render/partials.rb +15 -41
- data/lib/action_view/render/rendering.rb +27 -78
- data/lib/action_view/template.rb +20 -24
- data/lib/action_view/template/error.rb +22 -2
- data/lib/action_view/template/handlers/erb.rb +33 -9
- data/lib/action_view/template/handlers/rjs.rb +1 -2
- data/lib/action_view/template/resolver.rb +46 -104
- data/lib/action_view/template/text.rb +5 -12
- data/lib/action_view/test_case.rb +14 -23
- metadata +83 -40
- data/lib/abstract_controller/compatibility.rb +0 -18
- data/lib/abstract_controller/localized_cache.rb +0 -49
- data/lib/action_controller/metal/configuration.rb +0 -28
- data/lib/action_controller/url_rewriter.rb +0 -76
@@ -5,7 +5,7 @@ module ActionDispatch
|
|
5
5
|
#
|
6
6
|
# For backward compatibility, the post \format is extracted from the
|
7
7
|
# X-Post-Data-Format HTTP header if present.
|
8
|
-
def
|
8
|
+
def content_mime_type
|
9
9
|
@env["action_dispatch.request.content_type"] ||= begin
|
10
10
|
if @env['CONTENT_TYPE'] =~ /^([^,\;]*)/
|
11
11
|
Mime::Type.lookup($1.strip.downcase)
|
@@ -15,13 +15,17 @@ module ActionDispatch
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
def content_type
|
19
|
+
content_mime_type && content_mime_type.to_s
|
20
|
+
end
|
21
|
+
|
18
22
|
# Returns the accepted MIME type for the request.
|
19
23
|
def accepts
|
20
24
|
@env["action_dispatch.request.accepts"] ||= begin
|
21
25
|
header = @env['HTTP_ACCEPT'].to_s.strip
|
22
26
|
|
23
27
|
if header.empty?
|
24
|
-
[
|
28
|
+
[content_mime_type]
|
25
29
|
else
|
26
30
|
Mime::Type.parse(header)
|
27
31
|
end
|
@@ -67,21 +71,6 @@ module ActionDispatch
|
|
67
71
|
@env["action_dispatch.request.formats"] = [Mime::Type.lookup_by_extension(parameters[:format])]
|
68
72
|
end
|
69
73
|
|
70
|
-
# Returns a symbolized version of the <tt>:format</tt> parameter of the request.
|
71
|
-
# If no \format is given it returns <tt>:js</tt>for Ajax requests and <tt>:html</tt>
|
72
|
-
# otherwise.
|
73
|
-
def template_format
|
74
|
-
parameter_format = parameters[:format]
|
75
|
-
|
76
|
-
if parameter_format
|
77
|
-
parameter_format
|
78
|
-
elsif xhr?
|
79
|
-
:js
|
80
|
-
else
|
81
|
-
:html
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
74
|
# Receives an array of mimes and return the first user sent mime that
|
86
75
|
# matches the order array.
|
87
76
|
#
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'set'
|
2
2
|
require 'active_support/core_ext/class/attribute_accessors'
|
3
|
+
require 'active_support/core_ext/object/blank'
|
3
4
|
|
4
5
|
module Mime
|
5
6
|
class Mimes < Array
|
@@ -52,12 +53,6 @@ module Mime
|
|
52
53
|
cattr_reader :browser_generated_types
|
53
54
|
attr_reader :symbol
|
54
55
|
|
55
|
-
@@unverifiable_types = Set.new [:text, :json, :csv, :xml, :rss, :atom, :yaml]
|
56
|
-
def self.unverifiable_types
|
57
|
-
ActiveSupport::Deprecation.warn("unverifiable_types is deprecated and has no effect", caller)
|
58
|
-
@@unverifiable_types
|
59
|
-
end
|
60
|
-
|
61
56
|
# A simple helper class used in parsing the accept header
|
62
57
|
class AcceptItem #:nodoc:
|
63
58
|
attr_accessor :order, :name, :q
|
@@ -100,7 +95,7 @@ module Mime
|
|
100
95
|
end
|
101
96
|
|
102
97
|
def register(string, symbol, mime_type_synonyms = [], extension_synonyms = [], skip_lookup = false)
|
103
|
-
Mime.
|
98
|
+
Mime.const_set(symbol.to_s.upcase, Type.new(string, symbol, mime_type_synonyms))
|
104
99
|
|
105
100
|
SET << Mime.const_get(symbol.to_s.upcase)
|
106
101
|
|
@@ -30,6 +30,14 @@ module ActionDispatch
|
|
30
30
|
METHOD
|
31
31
|
end
|
32
32
|
|
33
|
+
def self.new(env)
|
34
|
+
if request = env["action_dispatch.request"] && request.instance_of?(self)
|
35
|
+
return request
|
36
|
+
end
|
37
|
+
|
38
|
+
super
|
39
|
+
end
|
40
|
+
|
33
41
|
def key?(key)
|
34
42
|
@env.key?(key)
|
35
43
|
end
|
@@ -88,11 +96,11 @@ module ActionDispatch
|
|
88
96
|
end
|
89
97
|
|
90
98
|
def forgery_whitelisted?
|
91
|
-
method == :get || xhr? ||
|
99
|
+
method == :get || xhr? || content_mime_type.nil? || !content_mime_type.verify_request?
|
92
100
|
end
|
93
101
|
|
94
102
|
def media_type
|
95
|
-
|
103
|
+
content_mime_type.to_s
|
96
104
|
end
|
97
105
|
|
98
106
|
# Returns the content length of the request as an integer.
|
@@ -119,36 +127,7 @@ module ActionDispatch
|
|
119
127
|
# delimited list in the case of multiple chained proxies; the last
|
120
128
|
# address which is not trusted is the originating IP.
|
121
129
|
def remote_ip
|
122
|
-
|
123
|
-
|
124
|
-
unless remote_addr_list.blank?
|
125
|
-
not_trusted_addrs = remote_addr_list.reject {|addr| addr =~ TRUSTED_PROXIES || addr =~ ActionController::Base.trusted_proxies}
|
126
|
-
return not_trusted_addrs.first unless not_trusted_addrs.empty?
|
127
|
-
end
|
128
|
-
remote_ips = @env['HTTP_X_FORWARDED_FOR'] && @env['HTTP_X_FORWARDED_FOR'].split(',')
|
129
|
-
|
130
|
-
if @env.include? 'HTTP_CLIENT_IP'
|
131
|
-
if ActionController::Base.ip_spoofing_check && remote_ips && !remote_ips.include?(@env['HTTP_CLIENT_IP'])
|
132
|
-
# We don't know which came from the proxy, and which from the user
|
133
|
-
raise ActionController::ActionControllerError.new <<EOM
|
134
|
-
IP spoofing attack?!
|
135
|
-
HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect}
|
136
|
-
HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect}
|
137
|
-
EOM
|
138
|
-
end
|
139
|
-
|
140
|
-
return @env['HTTP_CLIENT_IP']
|
141
|
-
end
|
142
|
-
|
143
|
-
if remote_ips
|
144
|
-
while remote_ips.size > 1 && (TRUSTED_PROXIES =~ remote_ips.last.strip || ActionController::Base.trusted_proxies =~ remote_ips.last.strip)
|
145
|
-
remote_ips.pop
|
146
|
-
end
|
147
|
-
|
148
|
-
return remote_ips.last.strip
|
149
|
-
end
|
150
|
-
|
151
|
-
@env['REMOTE_ADDR']
|
130
|
+
(@env["action_dispatch.remote_ip"] || ip).to_s
|
152
131
|
end
|
153
132
|
|
154
133
|
# Returns the lowercase name of the HTTP server software.
|
@@ -178,7 +157,7 @@ EOM
|
|
178
157
|
end
|
179
158
|
|
180
159
|
def form_data?
|
181
|
-
FORM_DATA_MEDIA_TYPES.include?(
|
160
|
+
FORM_DATA_MEDIA_TYPES.include?(content_mime_type.to_s)
|
182
161
|
end
|
183
162
|
|
184
163
|
def body_stream #:nodoc:
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'digest/md5'
|
2
2
|
require 'active_support/core_ext/module/delegation'
|
3
|
+
require 'active_support/core_ext/object/blank'
|
3
4
|
|
4
5
|
module ActionDispatch # :nodoc:
|
5
6
|
# Represents an HTTP response generated by a controller action. One can use
|
@@ -32,31 +33,38 @@ module ActionDispatch # :nodoc:
|
|
32
33
|
# end
|
33
34
|
# end
|
34
35
|
class Response < Rack::Response
|
35
|
-
include ActionDispatch::Http::Cache::Response
|
36
|
-
|
37
36
|
attr_accessor :request, :blank
|
38
37
|
|
39
38
|
attr_writer :header, :sending_file
|
40
39
|
alias_method :headers=, :header=
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
41
|
+
module Setup
|
42
|
+
def initialize(status = 200, header = {}, body = [])
|
43
|
+
@writer = lambda { |x| @body << x }
|
44
|
+
@block = nil
|
45
|
+
@length = 0
|
46
46
|
|
47
|
-
|
48
|
-
|
49
|
-
@length = 0
|
47
|
+
@status, @header = status, header
|
48
|
+
self.body = body
|
50
49
|
|
51
|
-
|
52
|
-
|
50
|
+
@cookie = []
|
51
|
+
@sending_file = false
|
53
52
|
|
54
|
-
|
55
|
-
|
53
|
+
@blank = false
|
54
|
+
|
55
|
+
if content_type = self["Content-Type"]
|
56
|
+
type, charset = content_type.split(/;\s*charset=/)
|
57
|
+
@content_type = Mime::Type.lookup(type)
|
58
|
+
@charset = charset || "UTF-8"
|
59
|
+
end
|
56
60
|
|
57
|
-
|
61
|
+
yield self if block_given?
|
62
|
+
end
|
58
63
|
end
|
59
64
|
|
65
|
+
include Setup
|
66
|
+
include ActionDispatch::Http::Cache::Response
|
67
|
+
|
60
68
|
def status=(status)
|
61
69
|
@status = Rack::Utils.status_code(status)
|
62
70
|
end
|
@@ -76,6 +84,18 @@ module ActionDispatch # :nodoc:
|
|
76
84
|
end
|
77
85
|
alias_method :status_message, :message
|
78
86
|
|
87
|
+
def respond_to?(method)
|
88
|
+
if method.to_sym == :to_path
|
89
|
+
@body.respond_to?(:to_path)
|
90
|
+
else
|
91
|
+
super
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def to_path
|
96
|
+
@body.to_path
|
97
|
+
end
|
98
|
+
|
79
99
|
def body
|
80
100
|
str = ''
|
81
101
|
each { |part| str << part.to_s }
|
@@ -120,7 +140,7 @@ module ActionDispatch # :nodoc:
|
|
120
140
|
assign_default_content_type_and_charset!
|
121
141
|
handle_conditional_get!
|
122
142
|
self["Set-Cookie"] = @cookie.join("\n") unless @cookie.blank?
|
123
|
-
self["ETag"] = @
|
143
|
+
self["ETag"] = @_etag if @_etag
|
124
144
|
super
|
125
145
|
end
|
126
146
|
|
@@ -3,7 +3,7 @@ module ActionDispatch
|
|
3
3
|
module URL
|
4
4
|
# Returns the complete URL used for this request.
|
5
5
|
def url
|
6
|
-
protocol + host_with_port +
|
6
|
+
protocol + host_with_port + fullpath
|
7
7
|
end
|
8
8
|
|
9
9
|
# Returns 'https://' if this is an SSL request and 'http://' otherwise.
|
@@ -81,42 +81,15 @@ module ActionDispatch
|
|
81
81
|
parts[0..-(tld_length+2)]
|
82
82
|
end
|
83
83
|
|
84
|
-
|
85
|
-
|
86
|
-
@env['QUERY_STRING'].present? ? @env['QUERY_STRING'] : (@env['REQUEST_URI'].to_s.split('?', 2)[1] || '')
|
84
|
+
def subdomain(tld_length = 1)
|
85
|
+
subdomains(tld_length).join('.')
|
87
86
|
end
|
88
87
|
|
89
88
|
# Returns the request URI, accounting for server idiosyncrasies.
|
90
89
|
# WEBrick includes the full URL. IIS leaves REQUEST_URI blank.
|
91
90
|
def request_uri
|
92
|
-
|
93
|
-
|
94
|
-
(%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri
|
95
|
-
else
|
96
|
-
# Construct IIS missing REQUEST_URI from SCRIPT_NAME and PATH_INFO.
|
97
|
-
uri = @env['PATH_INFO'].to_s
|
98
|
-
|
99
|
-
if script_filename = @env['SCRIPT_NAME'].to_s.match(%r{[^/]+$})
|
100
|
-
uri = uri.sub(/#{script_filename}\//, '')
|
101
|
-
end
|
102
|
-
|
103
|
-
env_qs = @env['QUERY_STRING'].to_s
|
104
|
-
uri += "?#{env_qs}" unless env_qs.empty?
|
105
|
-
|
106
|
-
if uri.blank?
|
107
|
-
@env.delete('REQUEST_URI')
|
108
|
-
else
|
109
|
-
@env['REQUEST_URI'] = uri
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
|
114
|
-
# Returns the interpreted \path to requested resource after all the installation
|
115
|
-
# directory of this application was taken into account.
|
116
|
-
def path
|
117
|
-
path = request_uri.to_s[/\A[^\?]*/]
|
118
|
-
path.sub!(/\A#{ActionController::Base.relative_url_root}/, '')
|
119
|
-
path
|
91
|
+
ActiveSupport::Deprecation.warn "Using #request_uri is deprecated. Use fullpath instead.", caller
|
92
|
+
fullpath
|
120
93
|
end
|
121
94
|
|
122
95
|
private
|
@@ -84,6 +84,7 @@ module ActionDispatch
|
|
84
84
|
|
85
85
|
options[:path] ||= "/"
|
86
86
|
@set_cookies[key] = options
|
87
|
+
@delete_cookies.delete(key)
|
87
88
|
value
|
88
89
|
end
|
89
90
|
|
@@ -167,12 +168,12 @@ module ActionDispatch
|
|
167
168
|
|
168
169
|
class SignedCookieJar < CookieJar #:nodoc:
|
169
170
|
def initialize(parent_jar)
|
170
|
-
unless ActionController::Base.
|
171
|
-
raise "You must set ActionController::Base.
|
171
|
+
unless ActionController::Base.config.secret
|
172
|
+
raise "You must set ActionController::Base.config.secret"
|
172
173
|
end
|
173
174
|
|
174
175
|
@parent_jar = parent_jar
|
175
|
-
@verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.
|
176
|
+
@verifier = ActiveSupport::MessageVerifier.new(ActionController::Base.config.secret)
|
176
177
|
end
|
177
178
|
|
178
179
|
def [](name)
|
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'active_support/json'
|
2
1
|
require 'action_dispatch/http/request'
|
3
2
|
|
4
3
|
module ActionDispatch
|
@@ -26,7 +25,9 @@ module ActionDispatch
|
|
26
25
|
|
27
26
|
return false if request.content_length.zero?
|
28
27
|
|
29
|
-
mime_type = content_type_from_legacy_post_data_format_header(env) ||
|
28
|
+
mime_type = content_type_from_legacy_post_data_format_header(env) ||
|
29
|
+
request.content_mime_type
|
30
|
+
|
30
31
|
strategy = @parsers[mime_type]
|
31
32
|
|
32
33
|
return false unless strategy
|
@@ -54,7 +55,7 @@ module ActionDispatch
|
|
54
55
|
|
55
56
|
raise
|
56
57
|
{ "body" => request.raw_post,
|
57
|
-
"content_type" => request.
|
58
|
+
"content_type" => request.content_mime_type,
|
58
59
|
"content_length" => request.content_length,
|
59
60
|
"exception" => "#{e.message} (#{e.class})",
|
60
61
|
"backtrace" => e.backtrace }
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module ActionDispatch
|
2
|
+
class RemoteIp
|
3
|
+
class IpSpoofAttackError < StandardError ; end
|
4
|
+
|
5
|
+
class RemoteIpGetter
|
6
|
+
def initialize(env, check_ip_spoofing, trusted_proxies)
|
7
|
+
@env = env
|
8
|
+
@check_ip_spoofing = check_ip_spoofing
|
9
|
+
@trusted_proxies = trusted_proxies
|
10
|
+
end
|
11
|
+
|
12
|
+
def remote_addrs
|
13
|
+
@remote_addrs ||= begin
|
14
|
+
list = @env['REMOTE_ADDR'] ? @env['REMOTE_ADDR'].split(/[,\s]+/) : []
|
15
|
+
list.reject { |addr| addr =~ @trusted_proxies }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
return remote_addrs.first if remote_addrs.any?
|
21
|
+
|
22
|
+
forwarded_ips = @env['HTTP_X_FORWARDED_FOR'] ? @env['HTTP_X_FORWARDED_FOR'].strip.split(/[,\s]+/) : []
|
23
|
+
|
24
|
+
if client_ip = @env['HTTP_CLIENT_IP']
|
25
|
+
if @check_ip_spoofing && !forwarded_ips.include?(client_ip)
|
26
|
+
# We don't know which came from the proxy, and which from the user
|
27
|
+
raise IpSpoofAttackError, "IP spoofing attack?!" \
|
28
|
+
"HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect}" \
|
29
|
+
"HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect}"
|
30
|
+
end
|
31
|
+
return client_ip
|
32
|
+
end
|
33
|
+
|
34
|
+
return forwarded_ips.reject { |ip| ip =~ @trusted_proxies }.last || @env["REMOTE_ADDR"]
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def initialize(app, check_ip_spoofing = true, trusted_proxies = nil)
|
39
|
+
@app = app
|
40
|
+
@check_ip_spoofing = check_ip_spoofing
|
41
|
+
regex = '(^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\.)'
|
42
|
+
regex << "|(#{trusted_proxies})" if trusted_proxies
|
43
|
+
@trusted_proxies = Regexp.new(regex, "i")
|
44
|
+
end
|
45
|
+
|
46
|
+
def call(env)
|
47
|
+
env["action_dispatch.remote_ip"] = RemoteIpGetter.new(env, @check_ip_spoofing, @trusted_proxies)
|
48
|
+
@app.call(env)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
require 'active_support/core_ext/hash/keys'
|
2
|
-
require '
|
2
|
+
require 'active_support/core_ext/object/blank'
|
3
3
|
|
4
4
|
module ActionDispatch
|
5
5
|
module Session
|
@@ -177,9 +177,8 @@ module ActionDispatch
|
|
177
177
|
if key.blank?
|
178
178
|
raise ArgumentError, 'A key is required to write a ' +
|
179
179
|
'cookie containing the session data. Use ' +
|
180
|
-
'config.action_controller.
|
181
|
-
'"_myapp_session"
|
182
|
-
'config/application.rb'
|
180
|
+
'config.action_controller.session_store :cookie_store, { :key => ' +
|
181
|
+
'"_myapp_session" } in config/application.rb'
|
183
182
|
end
|
184
183
|
end
|
185
184
|
|
@@ -193,10 +192,9 @@ module ActionDispatch
|
|
193
192
|
if secret.blank?
|
194
193
|
raise ArgumentError, "A secret is required to generate an " +
|
195
194
|
"integrity hash for cookie session data. Use " +
|
196
|
-
"config.
|
197
|
-
"
|
198
|
-
"
|
199
|
-
"in config/environment.rb"
|
195
|
+
"config.cookie_secret = \"some secret phrase of at " +
|
196
|
+
"least #{SECRET_MIN_LENGTH} characters\"" +
|
197
|
+
"in config/application.rb"
|
200
198
|
end
|
201
199
|
|
202
200
|
if secret.length < SECRET_MIN_LENGTH
|