actionpack 3.0.20 → 3.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.
- data/CHANGELOG +88 -142
- data/MIT-LICENSE +1 -1
- data/README.rdoc +5 -6
- data/lib/abstract_controller.rb +1 -0
- data/lib/abstract_controller/asset_paths.rb +2 -2
- data/lib/abstract_controller/base.rb +24 -19
- data/lib/abstract_controller/callbacks.rb +19 -19
- data/lib/abstract_controller/helpers.rb +11 -13
- data/lib/abstract_controller/layouts.rb +4 -5
- data/lib/abstract_controller/railties/routes_helpers.rb +18 -0
- data/lib/abstract_controller/rendering.rb +34 -31
- data/lib/abstract_controller/url_for.rb +27 -0
- data/lib/abstract_controller/view_paths.rb +31 -6
- data/lib/action_controller.rb +5 -3
- data/lib/action_controller/base.rb +15 -16
- data/lib/action_controller/caching.rb +2 -2
- data/lib/action_controller/caching/actions.rb +11 -12
- data/lib/action_controller/caching/fragments.rb +41 -19
- data/lib/action_controller/caching/pages.rb +3 -9
- data/lib/action_controller/caching/sweeping.rb +0 -1
- data/lib/action_controller/deprecated.rb +1 -1
- data/lib/action_controller/log_subscriber.rb +1 -1
- data/lib/action_controller/metal.rb +78 -20
- data/lib/action_controller/metal/compatibility.rb +0 -9
- data/lib/action_controller/metal/conditional_get.rb +9 -9
- data/lib/action_controller/metal/data_streaming.rb +145 -0
- data/lib/action_controller/metal/force_ssl.rb +35 -0
- data/lib/action_controller/metal/head.rb +1 -1
- data/lib/action_controller/metal/helpers.rb +37 -44
- data/lib/action_controller/metal/hide_actions.rb +2 -3
- data/lib/action_controller/metal/http_authentication.rb +41 -38
- data/lib/action_controller/metal/implicit_render.rb +13 -13
- data/lib/action_controller/metal/instrumentation.rb +2 -2
- data/lib/action_controller/metal/mime_responds.rb +25 -19
- data/lib/action_controller/metal/params_wrapper.rb +224 -0
- data/lib/action_controller/metal/redirecting.rb +6 -2
- data/lib/action_controller/metal/renderers.rb +50 -36
- data/lib/action_controller/metal/rendering.rb +34 -25
- data/lib/action_controller/metal/request_forgery_protection.rb +18 -36
- data/lib/action_controller/metal/responder.rb +47 -12
- data/lib/action_controller/metal/streaming.rb +244 -138
- data/lib/action_controller/metal/testing.rb +0 -9
- data/lib/action_controller/metal/url_for.rb +12 -14
- data/lib/action_controller/railtie.rb +19 -37
- data/lib/action_controller/railties/paths.rb +24 -0
- data/lib/action_controller/record_identifier.rb +4 -10
- data/lib/action_controller/test_case.rb +36 -19
- data/lib/action_controller/vendor/html-scanner/html/node.rb +5 -5
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +3 -3
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -0
- data/lib/action_dispatch.rb +4 -1
- data/lib/action_dispatch/http/cache.rb +5 -32
- data/lib/action_dispatch/http/filter_parameters.rb +3 -1
- data/lib/action_dispatch/http/mime_negotiation.rb +22 -3
- data/lib/action_dispatch/http/mime_type.rb +45 -5
- data/lib/action_dispatch/http/rack_cache.rb +58 -0
- data/lib/action_dispatch/http/request.rb +27 -41
- data/lib/action_dispatch/http/response.rb +56 -54
- data/lib/action_dispatch/http/upload.rb +1 -11
- data/lib/action_dispatch/http/url.rb +102 -42
- data/lib/action_dispatch/middleware/callbacks.rb +8 -25
- data/lib/action_dispatch/middleware/closed_error.rb +7 -0
- data/lib/action_dispatch/middleware/cookies.rb +37 -15
- data/lib/action_dispatch/middleware/flash.rb +80 -11
- data/lib/action_dispatch/middleware/params_parser.rb +2 -2
- data/lib/action_dispatch/middleware/reloader.rb +76 -0
- data/lib/action_dispatch/middleware/session/abstract_store.rb +56 -226
- data/lib/action_dispatch/middleware/session/cookie_store.rb +20 -44
- data/lib/action_dispatch/middleware/session/mem_cache_store.rb +7 -46
- data/lib/action_dispatch/middleware/show_exceptions.rb +15 -2
- data/lib/action_dispatch/middleware/stack.rb +50 -17
- data/lib/action_dispatch/middleware/static.rb +41 -29
- data/lib/action_dispatch/middleware/templates/rescues/_request_and_response.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/_trace.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/diagnostics.erb +3 -3
- data/lib/action_dispatch/middleware/templates/rescues/layout.erb +4 -2
- data/lib/action_dispatch/middleware/templates/rescues/template_error.erb +2 -6
- data/lib/action_dispatch/railtie.rb +8 -0
- data/lib/action_dispatch/routing.rb +13 -1
- data/lib/action_dispatch/routing/mapper.rb +345 -227
- data/lib/action_dispatch/routing/polymorphic_routes.rb +33 -13
- data/lib/action_dispatch/routing/redirection.rb +110 -0
- data/lib/action_dispatch/routing/route.rb +15 -13
- data/lib/action_dispatch/routing/route_set.rb +116 -90
- data/lib/action_dispatch/routing/routes_proxy.rb +35 -0
- data/lib/action_dispatch/routing/url_for.rb +25 -1
- data/lib/action_dispatch/testing/assertions/response.rb +8 -10
- data/lib/action_dispatch/testing/assertions/routing.rb +15 -15
- data/lib/action_dispatch/testing/assertions/selector.rb +13 -220
- data/lib/action_dispatch/testing/integration.rb +37 -28
- data/lib/action_dispatch/testing/performance_test.rb +1 -3
- data/lib/action_dispatch/testing/test_process.rb +1 -1
- data/lib/action_dispatch/testing/test_request.rb +9 -3
- data/lib/action_dispatch/testing/test_response.rb +4 -111
- data/lib/action_pack.rb +1 -1
- data/lib/action_pack/version.rb +3 -3
- data/lib/action_view.rb +39 -24
- data/lib/action_view/base.rb +61 -86
- data/lib/action_view/buffers.rb +43 -0
- data/lib/action_view/context.rb +21 -24
- data/lib/action_view/flows.rb +79 -0
- data/lib/action_view/helpers.rb +8 -6
- data/lib/action_view/helpers/active_model_helper.rb +0 -23
- data/lib/action_view/helpers/asset_paths.rb +79 -0
- data/lib/action_view/helpers/asset_tag_helper.rb +30 -500
- data/lib/action_view/helpers/asset_tag_helpers/asset_include_tag.rb +147 -0
- data/lib/action_view/helpers/asset_tag_helpers/asset_paths.rb +101 -0
- data/lib/action_view/helpers/asset_tag_helpers/javascript_tag_helpers.rb +200 -0
- data/lib/action_view/helpers/asset_tag_helpers/stylesheet_tag_helpers.rb +152 -0
- data/lib/action_view/helpers/atom_feed_helper.rb +2 -2
- data/lib/action_view/helpers/cache_helper.rb +11 -19
- data/lib/action_view/helpers/capture_helper.rb +19 -8
- data/lib/action_view/helpers/controller_helper.rb +21 -0
- data/lib/action_view/helpers/csrf_helper.rb +22 -4
- data/lib/action_view/helpers/date_helper.rb +36 -22
- data/lib/action_view/helpers/form_helper.rb +199 -113
- data/lib/action_view/helpers/form_options_helper.rb +10 -11
- data/lib/action_view/helpers/form_tag_helper.rb +94 -22
- data/lib/action_view/helpers/javascript_helper.rb +24 -107
- data/lib/action_view/helpers/number_helper.rb +36 -33
- data/lib/action_view/helpers/output_safety_helper.rb +38 -0
- data/lib/action_view/helpers/record_tag_helper.rb +6 -6
- data/lib/action_view/helpers/rendering_helper.rb +90 -0
- data/lib/action_view/helpers/sanitize_helper.rb +2 -2
- data/lib/action_view/helpers/sprockets_helper.rb +69 -0
- data/lib/action_view/helpers/tag_helper.rb +34 -12
- data/lib/action_view/helpers/text_helper.rb +30 -145
- data/lib/action_view/helpers/translation_helper.rb +10 -17
- data/lib/action_view/helpers/url_helper.rb +70 -67
- data/lib/action_view/locale/en.yml +1 -1
- data/lib/action_view/lookup_context.rb +36 -14
- data/lib/action_view/{paths.rb → path_set.rb} +9 -8
- data/lib/action_view/railtie.rb +12 -4
- data/lib/action_view/renderer/abstract_renderer.rb +36 -0
- data/lib/action_view/{render/partials.rb → renderer/partial_renderer.rb} +147 -146
- data/lib/action_view/renderer/renderer.rb +54 -0
- data/lib/action_view/renderer/streaming_template_renderer.rb +106 -0
- data/lib/action_view/renderer/template_renderer.rb +74 -0
- data/lib/action_view/template.rb +91 -54
- data/lib/action_view/template/error.rb +11 -8
- data/lib/action_view/template/handler.rb +9 -1
- data/lib/action_view/template/handlers.rb +9 -9
- data/lib/action_view/template/handlers/builder.rb +4 -4
- data/lib/action_view/template/handlers/erb.rb +21 -41
- data/lib/action_view/template/resolver.rb +171 -57
- data/lib/action_view/template/text.rb +0 -4
- data/lib/action_view/test_case.rb +32 -16
- data/lib/action_view/testing/resolvers.rb +16 -10
- data/lib/sprockets/railtie.rb +100 -0
- metadata +162 -140
- checksums.yaml +0 -7
- data/lib/action_controller/deprecated/base.rb +0 -143
- data/lib/action_controller/deprecated/dispatcher.rb +0 -28
- data/lib/action_controller/deprecated/url_writer.rb +0 -14
- data/lib/action_dispatch/routing/deprecated_mapper.rb +0 -525
- data/lib/action_view/helpers/prototype_helper.rb +0 -851
- data/lib/action_view/helpers/raw_output_helper.rb +0 -18
- data/lib/action_view/helpers/scriptaculous_helper.rb +0 -263
- data/lib/action_view/render/layouts.rb +0 -83
- data/lib/action_view/render/rendering.rb +0 -67
- data/lib/action_view/template/handlers/rjs.rb +0 -17
@@ -39,10 +39,11 @@ module ActionDispatch
|
|
39
39
|
end
|
40
40
|
|
41
41
|
module Response
|
42
|
-
attr_reader :cache_control
|
42
|
+
attr_reader :cache_control, :etag
|
43
|
+
alias :etag? :etag
|
43
44
|
|
44
45
|
def initialize(*)
|
45
|
-
|
46
|
+
super
|
46
47
|
|
47
48
|
@cache_control = {}
|
48
49
|
@etag = self["ETag"]
|
@@ -50,8 +51,7 @@ module ActionDispatch
|
|
50
51
|
if cache_control = self["Cache-Control"]
|
51
52
|
cache_control.split(/,\s*/).each do |segment|
|
52
53
|
first, last = segment.split("=")
|
53
|
-
last
|
54
|
-
@cache_control[first.to_sym] = last
|
54
|
+
@cache_control[first.to_sym] = last || true
|
55
55
|
end
|
56
56
|
end
|
57
57
|
end
|
@@ -70,14 +70,6 @@ module ActionDispatch
|
|
70
70
|
headers['Last-Modified'] = utc_time.httpdate
|
71
71
|
end
|
72
72
|
|
73
|
-
def etag
|
74
|
-
@etag
|
75
|
-
end
|
76
|
-
|
77
|
-
def etag?
|
78
|
-
@etag
|
79
|
-
end
|
80
|
-
|
81
73
|
def etag=(etag)
|
82
74
|
key = ActiveSupport::Cache.expand_cache_key(etag)
|
83
75
|
@etag = self["ETag"] = %("#{Digest::MD5.hexdigest(key)}")
|
@@ -88,28 +80,9 @@ module ActionDispatch
|
|
88
80
|
def handle_conditional_get!
|
89
81
|
if etag? || last_modified? || !@cache_control.empty?
|
90
82
|
set_conditional_cache_control!
|
91
|
-
elsif nonempty_ok_response?
|
92
|
-
self.etag = body
|
93
|
-
|
94
|
-
if request && request.etag_matches?(etag)
|
95
|
-
self.status = 304
|
96
|
-
self.body = []
|
97
|
-
end
|
98
|
-
|
99
|
-
set_conditional_cache_control!
|
100
|
-
else
|
101
|
-
headers["Cache-Control"] = "no-cache"
|
102
83
|
end
|
103
84
|
end
|
104
85
|
|
105
|
-
def nonempty_ok_response?
|
106
|
-
@status == 200 && string_body?
|
107
|
-
end
|
108
|
-
|
109
|
-
def string_body?
|
110
|
-
!@blank && @body.respond_to?(:all?) && @body.all? { |part| part.is_a?(String) }
|
111
|
-
end
|
112
|
-
|
113
86
|
DEFAULT_CACHE_CONTROL = "max-age=0, private, must-revalidate"
|
114
87
|
|
115
88
|
def set_conditional_cache_control!
|
@@ -119,7 +92,7 @@ module ActionDispatch
|
|
119
92
|
|
120
93
|
if control.empty?
|
121
94
|
headers["Cache-Control"] = DEFAULT_CACHE_CONTROL
|
122
|
-
elsif
|
95
|
+
elsif control[:no_cache]
|
123
96
|
headers["Cache-Control"] = "no-cache"
|
124
97
|
else
|
125
98
|
extras = control[:extras]
|
@@ -26,6 +26,8 @@ module ActionDispatch
|
|
26
26
|
module FilterParameters
|
27
27
|
extend ActiveSupport::Concern
|
28
28
|
|
29
|
+
@@parameter_filter_for = {}
|
30
|
+
|
29
31
|
# Return a hash of parameters with all sensitive data replaced.
|
30
32
|
def filtered_parameters
|
31
33
|
@filtered_parameters ||= parameter_filter.filter(parameters)
|
@@ -52,7 +54,7 @@ module ActionDispatch
|
|
52
54
|
end
|
53
55
|
|
54
56
|
def parameter_filter_for(filters)
|
55
|
-
ParameterFilter.new(filters)
|
57
|
+
@@parameter_filter_for[filters] ||= ParameterFilter.new(filters)
|
56
58
|
end
|
57
59
|
|
58
60
|
KV_RE = '[^&;=]+'
|
@@ -1,6 +1,13 @@
|
|
1
1
|
module ActionDispatch
|
2
2
|
module Http
|
3
3
|
module MimeNegotiation
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
mattr_accessor :ignore_accept_header
|
8
|
+
self.ignore_accept_header = false
|
9
|
+
end
|
10
|
+
|
4
11
|
# The MIME type of the HTTP request, such as Mime::XML.
|
5
12
|
#
|
6
13
|
# For backward compatibility, the post \format is extracted from the
|
@@ -43,13 +50,13 @@ module ActionDispatch
|
|
43
50
|
end
|
44
51
|
|
45
52
|
def formats
|
46
|
-
accept = @env['HTTP_ACCEPT']
|
47
|
-
|
48
53
|
@env["action_dispatch.request.formats"] ||=
|
49
54
|
if parameters[:format]
|
50
55
|
Array(Mime[parameters[:format]])
|
51
|
-
elsif
|
56
|
+
elsif use_accept_header && valid_accept_header
|
52
57
|
accepts
|
58
|
+
elsif xhr?
|
59
|
+
[Mime::JS]
|
53
60
|
else
|
54
61
|
[Mime::HTML]
|
55
62
|
end
|
@@ -85,6 +92,18 @@ module ActionDispatch
|
|
85
92
|
|
86
93
|
order.include?(Mime::ALL) ? formats.first : nil
|
87
94
|
end
|
95
|
+
|
96
|
+
protected
|
97
|
+
|
98
|
+
BROWSER_LIKE_ACCEPTS = /,\s*\*\/\*|\*\/\*\s*,/
|
99
|
+
|
100
|
+
def valid_accept_header
|
101
|
+
xhr? || (accept && accept !~ BROWSER_LIKE_ACCEPTS)
|
102
|
+
end
|
103
|
+
|
104
|
+
def use_accept_header
|
105
|
+
!self.class.ignore_accept_header
|
106
|
+
end
|
88
107
|
end
|
89
108
|
end
|
90
109
|
end
|
@@ -80,6 +80,9 @@ module Mime
|
|
80
80
|
end
|
81
81
|
|
82
82
|
class << self
|
83
|
+
|
84
|
+
TRAILING_STAR_REGEXP = /(text|application)\/\*/
|
85
|
+
|
83
86
|
def lookup(string)
|
84
87
|
LOOKUP[string]
|
85
88
|
end
|
@@ -105,15 +108,28 @@ module Mime
|
|
105
108
|
|
106
109
|
def parse(accept_header)
|
107
110
|
if accept_header !~ /,/
|
108
|
-
|
111
|
+
if accept_header =~ TRAILING_STAR_REGEXP
|
112
|
+
parse_data_with_trailing_star($1)
|
113
|
+
else
|
114
|
+
[Mime::Type.lookup(accept_header)]
|
115
|
+
end
|
109
116
|
else
|
110
117
|
# keep track of creation order to keep the subsequent sort stable
|
111
|
-
list = []
|
112
|
-
accept_header.split(/,/).
|
118
|
+
list, index = [], 0
|
119
|
+
accept_header.split(/,/).each do |header|
|
113
120
|
params, q = header.split(/;\s*q=/)
|
114
|
-
if params
|
121
|
+
if params.present?
|
115
122
|
params.strip!
|
116
|
-
|
123
|
+
|
124
|
+
if params =~ TRAILING_STAR_REGEXP
|
125
|
+
parse_data_with_trailing_star($1).each do |m|
|
126
|
+
list << AcceptItem.new(index, m.to_s, q)
|
127
|
+
index += 1
|
128
|
+
end
|
129
|
+
else
|
130
|
+
list << AcceptItem.new(index, params, q)
|
131
|
+
index += 1
|
132
|
+
end
|
117
133
|
end
|
118
134
|
end
|
119
135
|
list.sort!
|
@@ -160,6 +176,30 @@ module Mime
|
|
160
176
|
list
|
161
177
|
end
|
162
178
|
end
|
179
|
+
|
180
|
+
# input: 'text'
|
181
|
+
# returned value: [Mime::JSON, Mime::XML, Mime::ICS, Mime::HTML, Mime::CSS, Mime::CSV, Mime::JS, Mime::YAML, Mime::TEXT]
|
182
|
+
#
|
183
|
+
# input: 'application'
|
184
|
+
# returned value: [Mime::HTML, Mime::JS, Mime::XML, Mime::YAML, Mime::ATOM, Mime::JSON, Mime::RSS, Mime::URL_ENCODED_FORM]
|
185
|
+
def parse_data_with_trailing_star(input)
|
186
|
+
Mime::SET.select { |m| m =~ input }
|
187
|
+
end
|
188
|
+
|
189
|
+
# This method is opposite of register method.
|
190
|
+
#
|
191
|
+
# Usage:
|
192
|
+
#
|
193
|
+
# Mime::Type.unregister(:mobile)
|
194
|
+
def unregister(symbol)
|
195
|
+
symbol = symbol.to_s.upcase
|
196
|
+
mime = Mime.const_get(symbol)
|
197
|
+
Mime.instance_eval { remove_const(symbol) }
|
198
|
+
|
199
|
+
SET.delete_if { |v| v.eql?(mime) }
|
200
|
+
LOOKUP.delete_if { |k,v| v.eql?(mime) }
|
201
|
+
EXTENSION_LOOKUP.delete_if { |k,v| v.eql?(mime) }
|
202
|
+
end
|
163
203
|
end
|
164
204
|
|
165
205
|
def initialize(string, symbol = nil, synonyms = [])
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require "rack/cache"
|
2
|
+
require "rack/cache/context"
|
3
|
+
require "active_support/cache"
|
4
|
+
|
5
|
+
module ActionDispatch
|
6
|
+
class RailsMetaStore < Rack::Cache::MetaStore
|
7
|
+
def self.resolve(uri)
|
8
|
+
new
|
9
|
+
end
|
10
|
+
|
11
|
+
# TODO: Finally deal with the RAILS_CACHE global
|
12
|
+
def initialize(store = RAILS_CACHE)
|
13
|
+
@store = store
|
14
|
+
end
|
15
|
+
|
16
|
+
def read(key)
|
17
|
+
@store.read(key) || []
|
18
|
+
end
|
19
|
+
|
20
|
+
def write(key, value)
|
21
|
+
@store.write(key, value)
|
22
|
+
end
|
23
|
+
|
24
|
+
::Rack::Cache::MetaStore::RAILS = self
|
25
|
+
end
|
26
|
+
|
27
|
+
class RailsEntityStore < Rack::Cache::EntityStore
|
28
|
+
def self.resolve(uri)
|
29
|
+
new
|
30
|
+
end
|
31
|
+
|
32
|
+
def initialize(store = RAILS_CACHE)
|
33
|
+
@store = store
|
34
|
+
end
|
35
|
+
|
36
|
+
def exist?(key)
|
37
|
+
@store.exist?(key)
|
38
|
+
end
|
39
|
+
|
40
|
+
def open(key)
|
41
|
+
@store.read(key)
|
42
|
+
end
|
43
|
+
|
44
|
+
def read(key)
|
45
|
+
body = open(key)
|
46
|
+
body.join if body
|
47
|
+
end
|
48
|
+
|
49
|
+
def write(body)
|
50
|
+
buf = []
|
51
|
+
key, size = slurp(body) { |part| buf << part }
|
52
|
+
@store.write(key, buf)
|
53
|
+
[key, size]
|
54
|
+
end
|
55
|
+
|
56
|
+
::Rack::Cache::EntityStore::RAILS = self
|
57
|
+
end
|
58
|
+
end
|
@@ -17,16 +17,17 @@ module ActionDispatch
|
|
17
17
|
include ActionDispatch::Http::Upload
|
18
18
|
include ActionDispatch::Http::URL
|
19
19
|
|
20
|
-
LOCALHOST
|
21
|
-
|
22
|
-
%w[ AUTH_TYPE GATEWAY_INTERFACE
|
20
|
+
LOCALHOST = [/^127\.0\.0\.\d{1,3}$/, "::1", /^0:0:0:0:0:0:0:1(%.*)?$/].freeze
|
21
|
+
ENV_METHODS = %w[ AUTH_TYPE GATEWAY_INTERFACE
|
23
22
|
PATH_TRANSLATED REMOTE_HOST
|
24
23
|
REMOTE_IDENT REMOTE_USER REMOTE_ADDR
|
25
24
|
SERVER_NAME SERVER_PROTOCOL
|
26
25
|
|
27
26
|
HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_ACCEPT_ENCODING
|
28
27
|
HTTP_ACCEPT_LANGUAGE HTTP_CACHE_CONTROL HTTP_FROM
|
29
|
-
HTTP_NEGOTIATE HTTP_PRAGMA ].
|
28
|
+
HTTP_NEGOTIATE HTTP_PRAGMA ].freeze
|
29
|
+
|
30
|
+
ENV_METHODS.each do |env|
|
30
31
|
class_eval <<-METHOD, __FILE__, __LINE__ + 1
|
31
32
|
def #{env.sub(/^HTTP_/n, '').downcase}
|
32
33
|
@env["#{env}"]
|
@@ -72,11 +73,7 @@ module ActionDispatch
|
|
72
73
|
# the application should use), this \method returns the overridden
|
73
74
|
# value, not the original.
|
74
75
|
def request_method
|
75
|
-
@request_method ||=
|
76
|
-
method = env["REQUEST_METHOD"]
|
77
|
-
HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
|
78
|
-
method
|
79
|
-
end
|
76
|
+
@request_method ||= check_method(env["REQUEST_METHOD"])
|
80
77
|
end
|
81
78
|
|
82
79
|
# Returns a symbol form of the #request_method
|
@@ -88,11 +85,7 @@ module ActionDispatch
|
|
88
85
|
# even if it was overridden by middleware. See #request_method for
|
89
86
|
# more information.
|
90
87
|
def method
|
91
|
-
@method ||=
|
92
|
-
method = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD']
|
93
|
-
HTTP_METHOD_LOOKUP[method] || raise(ActionController::UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
|
94
|
-
method
|
95
|
-
end
|
88
|
+
@method ||= check_method(env["rack.methodoverride.original_method"] || env['REQUEST_METHOD'])
|
96
89
|
end
|
97
90
|
|
98
91
|
# Returns a symbol form of the #method
|
@@ -155,11 +148,11 @@ module ActionDispatch
|
|
155
148
|
super.to_i
|
156
149
|
end
|
157
150
|
|
158
|
-
# Returns true if the
|
159
|
-
#
|
160
|
-
# every Ajax request.
|
151
|
+
# Returns true if the "X-Requested-With" header contains "XMLHttpRequest"
|
152
|
+
# (case-insensitive). All major JavaScript libraries send this header with
|
153
|
+
# every Ajax request.
|
161
154
|
def xml_http_request?
|
162
|
-
|
155
|
+
@env['HTTP_X_REQUESTED_WITH'] =~ /XMLHttpRequest/i
|
163
156
|
end
|
164
157
|
alias :xhr? :xml_http_request?
|
165
158
|
|
@@ -168,8 +161,16 @@ module ActionDispatch
|
|
168
161
|
end
|
169
162
|
|
170
163
|
# Which IP addresses are "trusted proxies" that can be stripped from
|
171
|
-
# the right-hand-side of X-Forwarded-For
|
172
|
-
|
164
|
+
# the right-hand-side of X-Forwarded-For.
|
165
|
+
#
|
166
|
+
# http://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces.
|
167
|
+
TRUSTED_PROXIES = %r{
|
168
|
+
^127\.0\.0\.1$ | # localhost
|
169
|
+
^(10 | # private IP 10.x.x.x
|
170
|
+
172\.(1[6-9]|2[0-9]|3[0-1]) | # private IP in the range 172.16.0.0 .. 172.31.255.255
|
171
|
+
192\.168 # private IP 192.168.x.x
|
172
|
+
)\.
|
173
|
+
}x
|
173
174
|
|
174
175
|
# Determines originating IP address. REMOTE_ADDR is the standard
|
175
176
|
# but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or
|
@@ -233,13 +234,13 @@ module ActionDispatch
|
|
233
234
|
|
234
235
|
# Override Rack's GET method to support indifferent access
|
235
236
|
def GET
|
236
|
-
@env["action_dispatch.request.query_parameters"] ||= normalize_parameters(super)
|
237
|
+
@env["action_dispatch.request.query_parameters"] ||= (normalize_parameters(super) || {})
|
237
238
|
end
|
238
239
|
alias :query_parameters :GET
|
239
240
|
|
240
241
|
# Override Rack's POST method to support indifferent access
|
241
242
|
def POST
|
242
|
-
@env["action_dispatch.request.request_parameters"] ||= normalize_parameters(super)
|
243
|
+
@env["action_dispatch.request.request_parameters"] ||= (normalize_parameters(super) || {})
|
243
244
|
end
|
244
245
|
alias :request_parameters :POST
|
245
246
|
|
@@ -258,26 +259,11 @@ module ActionDispatch
|
|
258
259
|
LOCALHOST.any? { |local_ip| local_ip === remote_addr && local_ip === remote_ip }
|
259
260
|
end
|
260
261
|
|
261
|
-
|
262
|
-
def deep_munge(hash)
|
263
|
-
hash.each do |k, v|
|
264
|
-
case v
|
265
|
-
when Array
|
266
|
-
v.grep(Hash) { |x| deep_munge(x) }
|
267
|
-
v.compact!
|
268
|
-
hash[k] = nil if v.empty?
|
269
|
-
when Hash
|
270
|
-
deep_munge(v)
|
271
|
-
end
|
272
|
-
end
|
273
|
-
|
274
|
-
hash
|
275
|
-
end
|
276
|
-
|
277
|
-
protected
|
262
|
+
private
|
278
263
|
|
279
|
-
def
|
280
|
-
|
264
|
+
def check_method(name)
|
265
|
+
HTTP_METHOD_LOOKUP[name] || raise(ActionController::UnknownHttpMethod, "#{name}, accepted HTTP methods are #{HTTP_METHODS.to_sentence(:locale => :en)}")
|
266
|
+
name
|
281
267
|
end
|
282
268
|
end
|
283
269
|
end
|
@@ -32,24 +32,35 @@ module ActionDispatch # :nodoc:
|
|
32
32
|
# puts @response.body
|
33
33
|
# end
|
34
34
|
# end
|
35
|
-
class Response
|
36
|
-
attr_accessor :request, :
|
35
|
+
class Response
|
36
|
+
attr_accessor :request, :header, :status
|
37
|
+
attr_writer :sending_file
|
37
38
|
|
38
|
-
attr_writer :header, :sending_file
|
39
39
|
alias_method :headers=, :header=
|
40
|
+
alias_method :headers, :header
|
41
|
+
|
42
|
+
delegate :[], :[]=, :to => :@header
|
43
|
+
delegate :each, :to => :@body
|
44
|
+
|
45
|
+
# Sets the HTTP response's content MIME type. For example, in the controller
|
46
|
+
# you could write this:
|
47
|
+
#
|
48
|
+
# response.content_type = "text/plain"
|
49
|
+
#
|
50
|
+
# If a character set has been defined for this response (see charset=) then
|
51
|
+
# the character set information will also be included in the content type
|
52
|
+
# information.
|
53
|
+
attr_accessor :charset, :content_type
|
54
|
+
|
55
|
+
CONTENT_TYPE = "Content-Type"
|
56
|
+
|
57
|
+
cattr_accessor(:default_charset) { "utf-8" }
|
40
58
|
|
41
59
|
module Setup
|
42
60
|
def initialize(status = 200, header = {}, body = [])
|
43
|
-
|
44
|
-
@block = nil
|
45
|
-
@length = 0
|
46
|
-
|
47
|
-
@status, @header = status, header
|
48
|
-
self.body = body
|
61
|
+
self.body, self.header, self.status = body, header, status
|
49
62
|
|
50
|
-
@cookie = []
|
51
63
|
@sending_file = false
|
52
|
-
|
53
64
|
@blank = false
|
54
65
|
|
55
66
|
if content_type = self["Content-Type"]
|
@@ -62,6 +73,7 @@ module ActionDispatch # :nodoc:
|
|
62
73
|
end
|
63
74
|
end
|
64
75
|
|
76
|
+
include Rack::Response::Helpers
|
65
77
|
include Setup
|
66
78
|
include ActionDispatch::Http::Cache::Response
|
67
79
|
|
@@ -106,13 +118,29 @@ module ActionDispatch # :nodoc:
|
|
106
118
|
|
107
119
|
def body=(body)
|
108
120
|
@blank = true if body == EMPTY
|
109
|
-
|
121
|
+
|
122
|
+
# Explicitly check for strings. This is *wrong* theoretically
|
123
|
+
# but if we don't check this, the performance on string bodies
|
124
|
+
# is bad on Ruby 1.8 (because strings responds to each then).
|
125
|
+
@body = if body.respond_to?(:to_str) || !body.respond_to?(:each)
|
126
|
+
[body]
|
127
|
+
else
|
128
|
+
body
|
129
|
+
end
|
110
130
|
end
|
111
131
|
|
112
132
|
def body_parts
|
113
133
|
@body
|
114
134
|
end
|
115
135
|
|
136
|
+
def set_cookie(key, value)
|
137
|
+
::Rack::Utils.set_cookie_header!(header, key, value)
|
138
|
+
end
|
139
|
+
|
140
|
+
def delete_cookie(key, value={})
|
141
|
+
::Rack::Utils.delete_cookie_header!(header, key, value)
|
142
|
+
end
|
143
|
+
|
116
144
|
def location
|
117
145
|
headers['Location']
|
118
146
|
end
|
@@ -122,47 +150,21 @@ module ActionDispatch # :nodoc:
|
|
122
150
|
headers['Location'] = url
|
123
151
|
end
|
124
152
|
|
125
|
-
# Sets the HTTP response's content MIME type. For example, in the controller
|
126
|
-
# you could write this:
|
127
|
-
#
|
128
|
-
# response.content_type = "text/plain"
|
129
|
-
#
|
130
|
-
# If a character set has been defined for this response (see charset=) then
|
131
|
-
# the character set information will also be included in the content type
|
132
|
-
# information.
|
133
|
-
attr_accessor :charset, :content_type
|
134
|
-
|
135
|
-
CONTENT_TYPE = "Content-Type"
|
136
|
-
|
137
|
-
cattr_accessor(:default_charset) { "utf-8" }
|
138
|
-
|
139
153
|
def to_a
|
140
154
|
assign_default_content_type_and_charset!
|
141
155
|
handle_conditional_get!
|
142
|
-
self["Set-Cookie"] = self["Set-Cookie"].join("\n") if self["Set-Cookie"].respond_to?(:join)
|
143
|
-
self["ETag"] = @_etag if @_etag
|
144
|
-
super
|
145
|
-
end
|
146
156
|
|
147
|
-
|
157
|
+
@header["Set-Cookie"] = @header["Set-Cookie"].join("\n") if @header["Set-Cookie"].respond_to?(:join)
|
148
158
|
|
149
|
-
|
150
|
-
|
151
|
-
@
|
152
|
-
@body.call(self, self)
|
159
|
+
if [204, 304].include?(@status)
|
160
|
+
@header.delete "Content-Type"
|
161
|
+
[@status, @header, []]
|
153
162
|
else
|
154
|
-
@
|
163
|
+
[@status, @header, self]
|
155
164
|
end
|
156
|
-
|
157
|
-
@writer = callback
|
158
|
-
@block.call(self) if @block
|
159
|
-
end
|
160
|
-
|
161
|
-
def write(str)
|
162
|
-
str = str.to_s
|
163
|
-
@writer.call str
|
164
|
-
str
|
165
165
|
end
|
166
|
+
alias prepare! to_a
|
167
|
+
alias to_ary to_a # For implicit splat on 1.9.2
|
166
168
|
|
167
169
|
# Returns the response cookies, converted to a Hash of (name => value) pairs
|
168
170
|
#
|
@@ -181,18 +183,18 @@ module ActionDispatch # :nodoc:
|
|
181
183
|
cookies
|
182
184
|
end
|
183
185
|
|
184
|
-
|
185
|
-
def assign_default_content_type_and_charset!
|
186
|
-
return if headers[CONTENT_TYPE].present?
|
186
|
+
private
|
187
187
|
|
188
|
-
|
189
|
-
|
188
|
+
def assign_default_content_type_and_charset!
|
189
|
+
return if headers[CONTENT_TYPE].present?
|
190
190
|
|
191
|
-
|
192
|
-
|
191
|
+
@content_type ||= Mime::HTML
|
192
|
+
@charset ||= self.class.default_charset
|
193
193
|
|
194
|
-
|
195
|
-
|
194
|
+
type = @content_type.to_s.dup
|
195
|
+
type << "; charset=#{@charset}" unless @sending_file
|
196
196
|
|
197
|
+
headers[CONTENT_TYPE] = type
|
198
|
+
end
|
197
199
|
end
|
198
200
|
end
|