actionpack 2.1.2 → 2.2.2
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 +223 -7
- data/README +6 -12
- data/Rakefile +11 -11
- data/lib/action_controller.rb +9 -9
- data/lib/action_controller/assertions/response_assertions.rb +29 -78
- data/lib/action_controller/assertions/routing_assertions.rb +33 -33
- data/lib/action_controller/assertions/selector_assertions.rb +9 -5
- data/lib/action_controller/base.rb +227 -161
- data/lib/action_controller/benchmarking.rb +37 -24
- data/lib/action_controller/caching/actions.rb +53 -21
- data/lib/action_controller/caching/fragments.rb +10 -36
- data/lib/action_controller/caching/sweeping.rb +3 -3
- data/lib/action_controller/cgi_ext/session.rb +2 -22
- data/lib/action_controller/cgi_process.rb +8 -46
- data/lib/action_controller/components.rb +4 -1
- data/lib/action_controller/cookies.rb +10 -0
- data/lib/action_controller/dispatcher.rb +49 -15
- data/lib/action_controller/filters.rb +48 -10
- data/lib/action_controller/headers.rb +16 -14
- data/lib/action_controller/helpers.rb +2 -2
- data/lib/action_controller/http_authentication.rb +1 -1
- data/lib/action_controller/integration.rb +57 -60
- data/lib/action_controller/layout.rb +27 -53
- data/lib/action_controller/mime_responds.rb +5 -1
- data/lib/action_controller/mime_type.rb +64 -42
- data/lib/action_controller/mime_types.rb +2 -1
- data/lib/action_controller/performance_test.rb +16 -0
- data/lib/action_controller/polymorphic_routes.rb +16 -9
- data/lib/action_controller/rack_process.rb +303 -0
- data/lib/action_controller/request.rb +205 -97
- data/lib/action_controller/request_forgery_protection.rb +2 -2
- data/lib/action_controller/request_profiler.rb +0 -0
- data/lib/action_controller/rescue.rb +20 -115
- data/lib/action_controller/resources.rb +186 -83
- data/lib/action_controller/response.rb +140 -26
- data/lib/action_controller/routing.rb +28 -30
- data/lib/action_controller/routing/builder.rb +45 -54
- data/lib/action_controller/routing/optimisations.rb +31 -21
- data/lib/action_controller/routing/recognition_optimisation.rb +33 -27
- data/lib/action_controller/routing/route.rb +162 -147
- data/lib/action_controller/routing/route_set.rb +8 -7
- data/lib/action_controller/routing/routing_ext.rb +4 -1
- data/lib/action_controller/routing/segments.rb +50 -21
- data/lib/action_controller/session/cookie_store.rb +3 -2
- data/lib/action_controller/session/drb_server.rb +7 -7
- data/lib/action_controller/session_management.rb +6 -2
- data/lib/action_controller/streaming.rb +15 -8
- data/lib/action_controller/templates/rescues/diagnostics.erb +2 -2
- data/lib/action_controller/templates/rescues/template_error.erb +2 -2
- data/lib/action_controller/test_case.rb +66 -2
- data/lib/action_controller/test_process.rb +71 -66
- data/lib/action_controller/translation.rb +13 -0
- data/lib/action_controller/url_rewriter.rb +90 -13
- data/lib/action_controller/vendor/html-scanner/html/node.rb +9 -2
- data/lib/action_controller/vendor/html-scanner/html/sanitizer.rb +1 -1
- data/lib/action_controller/vendor/html-scanner/html/selector.rb +2 -2
- data/lib/action_controller/verification.rb +2 -2
- data/lib/action_pack/version.rb +1 -1
- data/lib/action_view.rb +19 -11
- data/lib/action_view/base.rb +184 -150
- data/lib/action_view/helpers.rb +38 -0
- data/lib/action_view/helpers/active_record_helper.rb +56 -27
- data/lib/action_view/helpers/asset_tag_helper.rb +356 -153
- data/lib/action_view/helpers/atom_feed_helper.rb +74 -19
- data/lib/action_view/helpers/benchmark_helper.rb +3 -3
- data/lib/action_view/helpers/cache_helper.rb +1 -2
- data/lib/action_view/helpers/capture_helper.rb +19 -44
- data/lib/action_view/helpers/date_helper.rb +486 -296
- data/lib/action_view/helpers/debug_helper.rb +20 -13
- data/lib/action_view/helpers/form_helper.rb +71 -30
- data/lib/action_view/helpers/form_options_helper.rb +15 -85
- data/lib/action_view/helpers/form_tag_helper.rb +61 -38
- data/lib/action_view/helpers/javascript_helper.rb +80 -89
- data/lib/action_view/helpers/number_helper.rb +179 -74
- data/lib/action_view/helpers/prototype_helper.rb +216 -201
- data/lib/action_view/helpers/record_tag_helper.rb +4 -5
- data/lib/action_view/helpers/sanitize_helper.rb +65 -33
- data/lib/action_view/helpers/scriptaculous_helper.rb +2 -2
- data/lib/action_view/helpers/tag_helper.rb +39 -22
- data/lib/action_view/helpers/text_helper.rb +212 -118
- data/lib/action_view/helpers/translation_helper.rb +21 -0
- data/lib/action_view/helpers/url_helper.rb +100 -58
- data/lib/action_view/inline_template.rb +13 -14
- data/lib/action_view/locale/en.yml +91 -0
- data/lib/action_view/partials.rb +100 -55
- data/lib/action_view/paths.rb +125 -0
- data/lib/action_view/renderable.rb +102 -0
- data/lib/action_view/renderable_partial.rb +48 -0
- data/lib/action_view/template.rb +90 -101
- data/lib/action_view/template_error.rb +11 -21
- data/lib/action_view/template_handler.rb +8 -28
- data/lib/action_view/template_handlers.rb +45 -0
- data/lib/action_view/template_handlers/builder.rb +5 -15
- data/lib/action_view/template_handlers/erb.rb +9 -6
- data/lib/action_view/template_handlers/rjs.rb +2 -17
- data/lib/action_view/test_case.rb +7 -4
- data/test/abstract_unit.rb +4 -1
- data/test/active_record_unit.rb +28 -30
- data/test/activerecord/render_partial_with_record_identification_test.rb +25 -12
- data/test/controller/action_pack_assertions_test.rb +8 -37
- data/test/controller/addresses_render_test.rb +0 -3
- data/test/controller/assert_select_test.rb +51 -24
- data/test/controller/base_test.rb +4 -4
- data/test/controller/caching_test.rb +136 -66
- data/test/controller/capture_test.rb +1 -21
- data/test/controller/cgi_test.rb +157 -10
- data/test/controller/components_test.rb +41 -25
- data/test/controller/content_type_test.rb +49 -17
- data/test/controller/cookie_test.rb +1 -1
- data/test/controller/deprecation/deprecated_base_methods_test.rb +0 -3
- data/test/controller/dispatcher_test.rb +9 -1
- data/test/controller/filter_params_test.rb +2 -2
- data/test/controller/filters_test.rb +13 -13
- data/test/controller/html-scanner/cdata_node_test.rb +15 -0
- data/test/controller/html-scanner/node_test.rb +21 -0
- data/test/controller/html-scanner/sanitizer_test.rb +14 -0
- data/test/controller/integration_test.rb +167 -6
- data/test/controller/layout_test.rb +11 -68
- data/test/controller/logging_test.rb +46 -0
- data/test/controller/mime_responds_test.rb +61 -59
- data/test/controller/mime_type_test.rb +6 -6
- data/test/controller/polymorphic_routes_test.rb +37 -2
- data/test/controller/rack_test.rb +323 -0
- data/test/controller/redirect_test.rb +72 -71
- data/test/controller/render_test.rb +1120 -108
- data/test/controller/request_forgery_protection_test.rb +66 -52
- data/test/controller/request_test.rb +103 -146
- data/test/controller/rescue_test.rb +20 -24
- data/test/controller/resources_test.rb +408 -25
- data/test/controller/routing_test.rb +1774 -1774
- data/test/controller/send_file_test.rb +0 -4
- data/test/controller/session/cookie_store_test.rb +53 -1
- data/test/controller/test_test.rb +15 -37
- data/test/controller/translation_test.rb +26 -0
- data/test/controller/url_rewriter_test.rb +27 -28
- data/test/controller/view_paths_test.rb +48 -47
- data/test/fixtures/_top_level_partial.html.erb +1 -0
- data/test/fixtures/_top_level_partial_only.erb +1 -0
- data/test/fixtures/developers/_developer.erb +1 -0
- data/test/fixtures/fun/games/_game.erb +1 -0
- data/test/fixtures/fun/serious/games/_game.erb +1 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.html.erb +3 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.js.rjs +6 -0
- data/test/fixtures/functional_caching/formatted_fragment_cached.xml.builder +5 -0
- data/test/fixtures/functional_caching/inline_fragment_cached.html.erb +2 -0
- data/test/fixtures/layouts/_column.html.erb +2 -0
- data/test/fixtures/projects/_project.erb +1 -0
- data/test/fixtures/public/javascripts/subdir/subdir.js +1 -0
- data/test/fixtures/public/stylesheets/subdir/subdir.css +1 -0
- data/test/fixtures/replies/_reply.erb +1 -0
- data/test/fixtures/test/_counter.html.erb +1 -0
- data/test/fixtures/test/_customer.erb +1 -1
- data/test/fixtures/test/_customer_with_var.erb +1 -0
- data/test/fixtures/test/_layout_for_block_with_args.html.erb +3 -0
- data/test/fixtures/test/_local_inspector.html.erb +1 -0
- data/test/fixtures/test/_partial_with_only_html_version.html.erb +1 -0
- data/test/fixtures/test/hello.builder +1 -1
- data/test/fixtures/test/hyphen-ated.erb +1 -0
- data/test/fixtures/test/implicit_content_type.atom.builder +2 -0
- data/test/fixtures/test/nested_layout.erb +3 -0
- data/test/fixtures/test/non_erb_block_content_for.builder +1 -1
- data/test/fixtures/test/sub_template_raise.html.erb +1 -0
- data/test/fixtures/test/template.erb +1 -0
- data/test/fixtures/test/using_layout_around_block_with_args.html.erb +1 -0
- data/test/template/active_record_helper_i18n_test.rb +46 -0
- data/test/template/active_record_helper_test.rb +24 -24
- data/test/template/asset_tag_helper_test.rb +161 -29
- data/test/template/atom_feed_helper_test.rb +114 -5
- data/test/template/compiled_templates_test.rb +59 -0
- data/test/template/date_helper_i18n_test.rb +113 -0
- data/test/template/date_helper_test.rb +403 -109
- data/test/template/form_helper_test.rb +213 -154
- data/test/template/form_options_helper_test.rb +249 -897
- data/test/template/form_tag_helper_test.rb +80 -32
- data/test/template/javascript_helper_test.rb +17 -18
- data/test/template/number_helper_i18n_test.rb +54 -0
- data/test/template/number_helper_test.rb +43 -13
- data/test/template/prototype_helper_test.rb +101 -84
- data/test/template/record_tag_helper_test.rb +24 -20
- data/test/template/render_test.rb +193 -0
- data/test/template/sanitize_helper_test.rb +3 -3
- data/test/template/tag_helper_test.rb +34 -14
- data/test/template/text_helper_test.rb +83 -9
- data/test/template/translation_helper_test.rb +28 -0
- data/test/template/url_helper_test.rb +55 -18
- metadata +57 -18
- data/lib/action_view/helpers/javascripts/controls.js +0 -963
- data/lib/action_view/helpers/javascripts/dragdrop.js +0 -972
- data/lib/action_view/helpers/javascripts/effects.js +0 -1120
- data/lib/action_view/helpers/javascripts/prototype.js +0 -4225
- data/lib/action_view/partial_template.rb +0 -70
- data/lib/action_view/template_finder.rb +0 -177
- data/lib/action_view/template_handlers/compilable.rb +0 -128
- data/test/controller/custom_handler_test.rb +0 -45
- data/test/controller/new_render_test.rb +0 -945
- data/test/fixtures/test/block_content_for.erb +0 -2
- data/test/fixtures/test/erb_content_for.erb +0 -2
- data/test/template/deprecated_erb_variable_test.rb +0 -9
- data/test/template/template_finder_test.rb +0 -73
- data/test/template/template_object_test.rb +0 -95
@@ -2,33 +2,38 @@ require 'tempfile'
|
|
2
2
|
require 'stringio'
|
3
3
|
require 'strscan'
|
4
4
|
|
5
|
-
|
6
|
-
# HTTP methods which are accepted by default.
|
7
|
-
ACCEPTED_HTTP_METHODS = Set.new(%w( get head put post delete options ))
|
5
|
+
require 'active_support/memoizable'
|
8
6
|
|
7
|
+
module ActionController
|
9
8
|
# CgiRequest and TestRequest provide concrete implementations.
|
10
9
|
class AbstractRequest
|
11
|
-
|
12
|
-
|
10
|
+
extend ActiveSupport::Memoizable
|
11
|
+
|
12
|
+
def self.relative_url_root=(relative_url_root)
|
13
|
+
ActiveSupport::Deprecation.warn(
|
14
|
+
"ActionController::AbstractRequest.relative_url_root= has been renamed." +
|
15
|
+
"You can now set it with config.action_controller.relative_url_root=", caller)
|
16
|
+
ActionController::Base.relative_url_root=relative_url_root
|
17
|
+
end
|
18
|
+
|
19
|
+
HTTP_METHODS = %w(get head put post delete options)
|
20
|
+
HTTP_METHOD_LOOKUP = HTTP_METHODS.inject({}) { |h, m| h[m] = h[m.upcase] = m.to_sym; h }
|
13
21
|
|
14
22
|
# The hash of environment variables for this request,
|
15
23
|
# such as { 'RAILS_ENV' => 'production' }.
|
16
24
|
attr_reader :env
|
17
25
|
|
18
|
-
# The true HTTP request method as a lowercase symbol, such as <tt>:get</tt>.
|
26
|
+
# The true HTTP request \method as a lowercase symbol, such as <tt>:get</tt>.
|
19
27
|
# UnknownHttpMethod is raised for invalid methods not listed in ACCEPTED_HTTP_METHODS.
|
20
28
|
def request_method
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
else
|
26
|
-
raise UnknownHttpMethod, "#{method}, accepted HTTP methods are #{ACCEPTED_HTTP_METHODS.to_a.to_sentence}"
|
27
|
-
end
|
28
|
-
end
|
29
|
+
method = @env['REQUEST_METHOD']
|
30
|
+
method = parameters[:_method] if method == 'POST' && !parameters[:_method].blank?
|
31
|
+
|
32
|
+
HTTP_METHOD_LOOKUP[method] || raise(UnknownHttpMethod, "#{method}, accepted HTTP methods are #{HTTP_METHODS.to_sentence}")
|
29
33
|
end
|
34
|
+
memoize :request_method
|
30
35
|
|
31
|
-
# The HTTP request method as a lowercase symbol, such as <tt>:get</tt>.
|
36
|
+
# The HTTP request \method as a lowercase symbol, such as <tt>:get</tt>.
|
32
37
|
# Note, HEAD is returned as <tt>:get</tt> since the two are functionally
|
33
38
|
# equivalent from the application's perspective.
|
34
39
|
def method
|
@@ -55,57 +60,107 @@ module ActionController
|
|
55
60
|
request_method == :delete
|
56
61
|
end
|
57
62
|
|
58
|
-
# Is this a HEAD request? <tt>request.method</tt> sees HEAD as <tt>:get</tt>,
|
59
|
-
#
|
63
|
+
# Is this a HEAD request? Since <tt>request.method</tt> sees HEAD as <tt>:get</tt>,
|
64
|
+
# this \method checks the actual HTTP \method directly.
|
60
65
|
def head?
|
61
66
|
request_method == :head
|
62
67
|
end
|
63
68
|
|
64
|
-
# Provides
|
65
|
-
#
|
69
|
+
# Provides access to the request's HTTP headers, for example:
|
70
|
+
#
|
71
|
+
# request.headers["Content-Type"] # => "text/plain"
|
66
72
|
def headers
|
67
|
-
|
73
|
+
ActionController::Http::Headers.new(@env)
|
68
74
|
end
|
75
|
+
memoize :headers
|
69
76
|
|
77
|
+
# Returns the content length of the request as an integer.
|
70
78
|
def content_length
|
71
|
-
@
|
79
|
+
@env['CONTENT_LENGTH'].to_i
|
72
80
|
end
|
81
|
+
memoize :content_length
|
73
82
|
|
74
83
|
# The MIME type of the HTTP request, such as Mime::XML.
|
75
84
|
#
|
76
|
-
# For backward compatibility, the post format is extracted from the
|
85
|
+
# For backward compatibility, the post \format is extracted from the
|
77
86
|
# X-Post-Data-Format HTTP header if present.
|
78
87
|
def content_type
|
79
|
-
|
88
|
+
Mime::Type.lookup(content_type_without_parameters)
|
80
89
|
end
|
90
|
+
memoize :content_type
|
81
91
|
|
82
|
-
# Returns the accepted MIME type for the request
|
92
|
+
# Returns the accepted MIME type for the request.
|
83
93
|
def accepts
|
84
|
-
@
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
94
|
+
header = @env['HTTP_ACCEPT'].to_s.strip
|
95
|
+
|
96
|
+
if header.empty?
|
97
|
+
[content_type, Mime::ALL].compact
|
98
|
+
else
|
99
|
+
Mime::Type.parse(header)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
memoize :accepts
|
103
|
+
|
104
|
+
def if_modified_since
|
105
|
+
if since = env['HTTP_IF_MODIFIED_SINCE']
|
106
|
+
Time.rfc2822(since) rescue nil
|
107
|
+
end
|
90
108
|
end
|
109
|
+
memoize :if_modified_since
|
91
110
|
|
92
|
-
|
93
|
-
|
111
|
+
def if_none_match
|
112
|
+
env['HTTP_IF_NONE_MATCH']
|
113
|
+
end
|
114
|
+
|
115
|
+
def not_modified?(modified_at)
|
116
|
+
if_modified_since && modified_at && if_modified_since >= modified_at
|
117
|
+
end
|
118
|
+
|
119
|
+
def etag_matches?(etag)
|
120
|
+
if_none_match && if_none_match == etag
|
121
|
+
end
|
122
|
+
|
123
|
+
# Check response freshness (Last-Modified and ETag) against request
|
124
|
+
# If-Modified-Since and If-None-Match conditions. If both headers are
|
125
|
+
# supplied, both must match, or the request is not considered fresh.
|
126
|
+
def fresh?(response)
|
127
|
+
case
|
128
|
+
when if_modified_since && if_none_match
|
129
|
+
not_modified?(response.last_modified) && etag_matches?(response.etag)
|
130
|
+
when if_modified_since
|
131
|
+
not_modified?(response.last_modified)
|
132
|
+
when if_none_match
|
133
|
+
etag_matches?(response.etag)
|
134
|
+
else
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# Returns the Mime type for the \format used in the request.
|
94
140
|
#
|
95
141
|
# GET /posts/5.xml | request.format => Mime::XML
|
96
142
|
# GET /posts/5.xhtml | request.format => Mime::HTML
|
97
|
-
# GET /posts/5 | request.format => request.accepts.first
|
143
|
+
# GET /posts/5 | request.format => Mime::HTML or MIME::JS, or request.accepts.first depending on the value of <tt>ActionController::Base.use_accept_header</tt>
|
98
144
|
def format
|
99
|
-
@format ||=
|
145
|
+
@format ||=
|
146
|
+
if parameters[:format]
|
147
|
+
Mime::Type.lookup_by_extension(parameters[:format])
|
148
|
+
elsif ActionController::Base.use_accept_header
|
149
|
+
accepts.first
|
150
|
+
elsif xhr?
|
151
|
+
Mime::Type.lookup_by_extension("js")
|
152
|
+
else
|
153
|
+
Mime::Type.lookup_by_extension("html")
|
154
|
+
end
|
100
155
|
end
|
101
|
-
|
102
|
-
|
103
|
-
# Sets the format by string extension, which can be used to force custom formats
|
104
|
-
#
|
156
|
+
|
157
|
+
|
158
|
+
# Sets the \format by string extension, which can be used to force custom formats
|
159
|
+
# that are not controlled by the extension.
|
105
160
|
#
|
106
161
|
# class ApplicationController < ActionController::Base
|
107
162
|
# before_filter :adjust_format_for_iphone
|
108
|
-
#
|
163
|
+
#
|
109
164
|
# private
|
110
165
|
# def adjust_format_for_iphone
|
111
166
|
# request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
|
@@ -116,6 +171,25 @@ module ActionController
|
|
116
171
|
@format = Mime::Type.lookup_by_extension(parameters[:format])
|
117
172
|
end
|
118
173
|
|
174
|
+
# Returns a symbolized version of the <tt>:format</tt> parameter of the request.
|
175
|
+
# If no \format is given it returns <tt>:js</tt>for Ajax requests and <tt>:html</tt>
|
176
|
+
# otherwise.
|
177
|
+
def template_format
|
178
|
+
parameter_format = parameters[:format]
|
179
|
+
|
180
|
+
if parameter_format
|
181
|
+
parameter_format
|
182
|
+
elsif xhr?
|
183
|
+
:js
|
184
|
+
else
|
185
|
+
:html
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
def cache_format
|
190
|
+
parameters[:format]
|
191
|
+
end
|
192
|
+
|
119
193
|
# Returns true if the request's "X-Requested-With" header contains
|
120
194
|
# "XMLHttpRequest". (The Prototype Javascript library sends this header with
|
121
195
|
# every Ajax request.)
|
@@ -128,7 +202,7 @@ module ActionController
|
|
128
202
|
# the right-hand-side of X-Forwarded-For
|
129
203
|
TRUSTED_PROXIES = /^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i
|
130
204
|
|
131
|
-
#
|
205
|
+
# Determines originating IP address. REMOTE_ADDR is the standard
|
132
206
|
# but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or
|
133
207
|
# HTTP_X_FORWARDED_FOR are set by proxies so check for these if
|
134
208
|
# REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma-
|
@@ -166,44 +240,65 @@ EOM
|
|
166
240
|
|
167
241
|
@env['REMOTE_ADDR']
|
168
242
|
end
|
243
|
+
memoize :remote_ip
|
169
244
|
|
170
245
|
# Returns the lowercase name of the HTTP server software.
|
171
246
|
def server_software
|
172
247
|
(@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil
|
173
248
|
end
|
249
|
+
memoize :server_software
|
174
250
|
|
175
251
|
|
176
|
-
# Returns the complete URL used for this request
|
252
|
+
# Returns the complete URL used for this request.
|
177
253
|
def url
|
178
254
|
protocol + host_with_port + request_uri
|
179
255
|
end
|
256
|
+
memoize :url
|
180
257
|
|
181
|
-
#
|
258
|
+
# Returns 'https://' if this is an SSL request and 'http://' otherwise.
|
182
259
|
def protocol
|
183
260
|
ssl? ? 'https://' : 'http://'
|
184
261
|
end
|
262
|
+
memoize :protocol
|
185
263
|
|
186
264
|
# Is this an SSL request?
|
187
265
|
def ssl?
|
188
266
|
@env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
|
189
267
|
end
|
190
268
|
|
269
|
+
# Returns the \host for this request, such as "example.com".
|
270
|
+
def raw_host_with_port
|
271
|
+
if forwarded = env["HTTP_X_FORWARDED_HOST"]
|
272
|
+
forwarded.split(/,\s?/).last
|
273
|
+
else
|
274
|
+
env['HTTP_HOST'] || env['SERVER_NAME'] || "#{env['SERVER_ADDR']}:#{env['SERVER_PORT']}"
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
191
278
|
# Returns the host for this request, such as example.com.
|
192
279
|
def host
|
280
|
+
raw_host_with_port.sub(/:\d+$/, '')
|
193
281
|
end
|
282
|
+
memoize :host
|
194
283
|
|
195
|
-
# Returns a host
|
196
|
-
# example.com:8080.
|
284
|
+
# Returns a \host:\port string for this request, such as "example.com" or
|
285
|
+
# "example.com:8080".
|
197
286
|
def host_with_port
|
198
|
-
|
287
|
+
"#{host}#{port_string}"
|
199
288
|
end
|
289
|
+
memoize :host_with_port
|
200
290
|
|
201
291
|
# Returns the port number of this request as an integer.
|
202
292
|
def port
|
203
|
-
|
293
|
+
if raw_host_with_port =~ /:(\d+)$/
|
294
|
+
$1.to_i
|
295
|
+
else
|
296
|
+
standard_port
|
297
|
+
end
|
204
298
|
end
|
299
|
+
memoize :port
|
205
300
|
|
206
|
-
# Returns the standard port number for this request's protocol
|
301
|
+
# Returns the standard \port number for this request's protocol.
|
207
302
|
def standard_port
|
208
303
|
case protocol
|
209
304
|
when 'https://' then 443
|
@@ -211,13 +306,13 @@ EOM
|
|
211
306
|
end
|
212
307
|
end
|
213
308
|
|
214
|
-
# Returns a port suffix like ":8080" if the port number of this request
|
215
|
-
# is not the default HTTP port 80 or HTTPS port 443.
|
309
|
+
# Returns a \port suffix like ":8080" if the \port number of this request
|
310
|
+
# is not the default HTTP \port 80 or HTTPS \port 443.
|
216
311
|
def port_string
|
217
|
-
|
312
|
+
port == standard_port ? '' : ":#{port}"
|
218
313
|
end
|
219
314
|
|
220
|
-
# Returns the domain part of a host, such as rubyonrails.org in "www.rubyonrails.org". You can specify
|
315
|
+
# Returns the \domain part of a \host, such as "rubyonrails.org" in "www.rubyonrails.org". You can specify
|
221
316
|
# a different <tt>tld_length</tt>, such as 2 to catch rubyonrails.co.uk in "www.rubyonrails.co.uk".
|
222
317
|
def domain(tld_length = 1)
|
223
318
|
return nil unless named_host?(host)
|
@@ -225,8 +320,9 @@ EOM
|
|
225
320
|
host.split('.').last(1 + tld_length).join('.')
|
226
321
|
end
|
227
322
|
|
228
|
-
# Returns all the subdomains as an array, so ["dev", "www"] would be
|
229
|
-
# You can specify a different <tt>tld_length</tt>,
|
323
|
+
# Returns all the \subdomains as an array, so <tt>["dev", "www"]</tt> would be
|
324
|
+
# returned for "dev.www.rubyonrails.org". You can specify a different <tt>tld_length</tt>,
|
325
|
+
# such as 2 to catch <tt>["www"]</tt> instead of <tt>["www", "rubyonrails"]</tt>
|
230
326
|
# in "www.rubyonrails.co.uk".
|
231
327
|
def subdomains(tld_length = 1)
|
232
328
|
return [] unless named_host?(host)
|
@@ -234,7 +330,7 @@ EOM
|
|
234
330
|
parts[0..-(tld_length+2)]
|
235
331
|
end
|
236
332
|
|
237
|
-
#
|
333
|
+
# Returns the query string, accounting for server idiosyncrasies.
|
238
334
|
def query_string
|
239
335
|
if uri = @env['REQUEST_URI']
|
240
336
|
uri.split('?', 2)[1] || ''
|
@@ -242,8 +338,9 @@ EOM
|
|
242
338
|
@env['QUERY_STRING'] || ''
|
243
339
|
end
|
244
340
|
end
|
341
|
+
memoize :query_string
|
245
342
|
|
246
|
-
#
|
343
|
+
# Returns the request URI, accounting for server idiosyncrasies.
|
247
344
|
# WEBrick includes the full URL. IIS leaves REQUEST_URI blank.
|
248
345
|
def request_uri
|
249
346
|
if uri = @env['REQUEST_URI']
|
@@ -251,48 +348,36 @@ EOM
|
|
251
348
|
(%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri
|
252
349
|
else
|
253
350
|
# Construct IIS missing REQUEST_URI from SCRIPT_NAME and PATH_INFO.
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
uri << '?' << env_qs
|
351
|
+
uri = @env['PATH_INFO'].to_s
|
352
|
+
|
353
|
+
if script_filename = @env['SCRIPT_NAME'].to_s.match(%r{[^/]+$})
|
354
|
+
uri = uri.sub(/#{script_filename}\//, '')
|
259
355
|
end
|
260
356
|
|
261
|
-
|
357
|
+
env_qs = @env['QUERY_STRING'].to_s
|
358
|
+
uri += "?#{env_qs}" unless env_qs.empty?
|
359
|
+
|
360
|
+
if uri.blank?
|
262
361
|
@env.delete('REQUEST_URI')
|
263
|
-
uri
|
264
362
|
else
|
265
363
|
@env['REQUEST_URI'] = uri
|
266
364
|
end
|
267
365
|
end
|
268
366
|
end
|
367
|
+
memoize :request_uri
|
269
368
|
|
270
|
-
# Returns the interpreted path to requested resource after all the installation
|
369
|
+
# Returns the interpreted \path to requested resource after all the installation
|
370
|
+
# directory of this application was taken into account.
|
271
371
|
def path
|
272
372
|
path = (uri = request_uri) ? uri.split('?').first.to_s : ''
|
273
373
|
|
274
374
|
# Cut off the path to the installation directory if given
|
275
|
-
path.sub!(%r/^#{relative_url_root}/, '')
|
276
|
-
path || ''
|
277
|
-
end
|
278
|
-
|
279
|
-
# Returns the path minus the web server relative installation directory.
|
280
|
-
# This can be set with the environment variable RAILS_RELATIVE_URL_ROOT.
|
281
|
-
# It can be automatically extracted for Apache setups. If the server is not
|
282
|
-
# Apache, this method returns an empty string.
|
283
|
-
def relative_url_root
|
284
|
-
@@relative_url_root ||= case
|
285
|
-
when @env["RAILS_RELATIVE_URL_ROOT"]
|
286
|
-
@env["RAILS_RELATIVE_URL_ROOT"]
|
287
|
-
when server_software == 'apache'
|
288
|
-
@env["SCRIPT_NAME"].to_s.sub(/\/dispatch\.(fcgi|rb|cgi)$/, '')
|
289
|
-
else
|
290
|
-
''
|
291
|
-
end
|
375
|
+
path.sub!(%r/^#{ActionController::Base.relative_url_root}/, '')
|
376
|
+
path || ''
|
292
377
|
end
|
378
|
+
memoize :path
|
293
379
|
|
294
|
-
|
295
|
-
# Read the request body. This is useful for web services that need to
|
380
|
+
# Read the request \body. This is useful for web services that need to
|
296
381
|
# work with raw requests directly.
|
297
382
|
def raw_post
|
298
383
|
unless env.include? 'RAW_POST_DATA'
|
@@ -302,7 +387,7 @@ EOM
|
|
302
387
|
env['RAW_POST_DATA']
|
303
388
|
end
|
304
389
|
|
305
|
-
# Returns both GET and POST parameters in a single hash.
|
390
|
+
# Returns both GET and POST \parameters in a single hash.
|
306
391
|
def parameters
|
307
392
|
@parameters ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access
|
308
393
|
end
|
@@ -312,34 +397,56 @@ EOM
|
|
312
397
|
@symbolized_path_parameters = @parameters = nil
|
313
398
|
end
|
314
399
|
|
315
|
-
# The same as <tt>path_parameters</tt> with explicitly symbolized keys
|
316
|
-
def symbolized_path_parameters
|
400
|
+
# The same as <tt>path_parameters</tt> with explicitly symbolized keys.
|
401
|
+
def symbolized_path_parameters
|
317
402
|
@symbolized_path_parameters ||= path_parameters.symbolize_keys
|
318
403
|
end
|
319
404
|
|
320
|
-
# Returns a hash with the parameters used to form the path of the request.
|
321
|
-
# Returned hash keys are strings
|
322
|
-
#
|
323
|
-
# Example:
|
405
|
+
# Returns a hash with the \parameters used to form the \path of the request.
|
406
|
+
# Returned hash keys are strings:
|
324
407
|
#
|
325
408
|
# {'action' => 'my_action', 'controller' => 'my_controller'}
|
409
|
+
#
|
410
|
+
# See <tt>symbolized_path_parameters</tt> for symbolized keys.
|
326
411
|
def path_parameters
|
327
412
|
@path_parameters ||= {}
|
328
413
|
end
|
329
414
|
|
415
|
+
# The request body is an IO input stream. If the RAW_POST_DATA environment
|
416
|
+
# variable is already set, wrap it in a StringIO.
|
417
|
+
def body
|
418
|
+
if raw_post = env['RAW_POST_DATA']
|
419
|
+
raw_post.force_encoding(Encoding::BINARY) if raw_post.respond_to?(:force_encoding)
|
420
|
+
StringIO.new(raw_post)
|
421
|
+
else
|
422
|
+
body_stream
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
def remote_addr
|
427
|
+
@env['REMOTE_ADDR']
|
428
|
+
end
|
330
429
|
|
331
|
-
|
332
|
-
|
333
|
-
|
430
|
+
def referrer
|
431
|
+
@env['HTTP_REFERER']
|
432
|
+
end
|
433
|
+
alias referer referrer
|
334
434
|
|
335
|
-
|
336
|
-
def
|
435
|
+
|
436
|
+
def query_parameters
|
437
|
+
@query_parameters ||= self.class.parse_query_parameters(query_string)
|
337
438
|
end
|
338
439
|
|
339
|
-
def
|
440
|
+
def request_parameters
|
441
|
+
@request_parameters ||= parse_formatted_request_parameters
|
340
442
|
end
|
341
443
|
|
342
|
-
|
444
|
+
|
445
|
+
#--
|
446
|
+
# Must be implemented in the concrete request
|
447
|
+
#++
|
448
|
+
|
449
|
+
def body_stream #:nodoc:
|
343
450
|
end
|
344
451
|
|
345
452
|
def cookies #:nodoc:
|
@@ -366,8 +473,9 @@ EOM
|
|
366
473
|
|
367
474
|
# The raw content type string with its parameters stripped off.
|
368
475
|
def content_type_without_parameters
|
369
|
-
|
476
|
+
self.class.extract_content_type_without_parameters(content_type_with_parameters)
|
370
477
|
end
|
478
|
+
memoize :content_type_without_parameters
|
371
479
|
|
372
480
|
private
|
373
481
|
def content_type_from_legacy_post_data_format_header
|