Class: ActionController::AbstractRequest
- Defined in:
- lib/action_controller/request.rb
Overview
CgiRequest and TestRequest provide concrete implementations.
Direct Known Subclasses
Constant Summary collapse
- TRUSTED_PROXIES =
Which IP addresses are “trusted proxies” that can be stripped from the right-hand-side of X-Forwarded-For
/^127\.0\.0\.1$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i
Instance Attribute Summary collapse
-
#env ⇒ Object
readonly
The hash of environment variables for this request, such as { ‘RAILS_ENV’ => ‘production’ }.
Class Method Summary collapse
- .clean_up_ajax_request_body!(body) ⇒ Object
- .extract_content_type_without_parameters(content_type_with_parameters) ⇒ Object
- .extract_multipart_boundary(content_type_with_parameters) ⇒ Object
- .parse_multipart_form_parameters(body, boundary, body_size, env) ⇒ Object
- .parse_query_parameters(query_string) ⇒ Object
- .parse_request_parameters(params) ⇒ Object
Instance Method Summary collapse
-
#accepts ⇒ Object
Returns the accepted MIME type for the request.
-
#body ⇒ Object
The request body is an IO input stream.
- #content_length ⇒ Object
-
#content_type ⇒ Object
The MIME type of the HTTP request, such as Mime::XML.
-
#cookies ⇒ Object
:nodoc:.
-
#delete? ⇒ Boolean
Is this a DELETE request? Equivalent to
request.method == :delete
. -
#domain(tld_length = 1) ⇒ Object
Returns the domain part of a host, such as rubyonrails.org in “www.rubyonrails.org”.
-
#format ⇒ Object
Returns the Mime type for the format used in the request.
-
#format=(extension) ⇒ Object
Sets the format by string extension, which can be used to force custom formats that are not controlled by the extension.
-
#get? ⇒ Boolean
Is this a GET (or HEAD) request? Equivalent to
request.method == :get
. -
#head? ⇒ Boolean
Is this a HEAD request?
request.method
sees HEAD as:get
, so check the HTTP method directly. -
#headers ⇒ Object
Provides acccess to the request’s HTTP headers, for example: request.headers # => “text/plain”.
-
#host ⇒ Object
Returns the host for this request, such as example.com.
-
#host_with_port ⇒ Object
Returns a host:port string for this request, such as example.com or example.com:8080.
-
#method ⇒ Object
The HTTP request method as a lowercase symbol, such as
:get
. -
#parameters ⇒ Object
Returns both GET and POST parameters in a single hash.
-
#path ⇒ Object
Returns the interpreted path to requested resource after all the installation directory of this application was taken into account.
-
#path_parameters ⇒ Object
Returns a hash with the parameters used to form the path of the request.
-
#path_parameters=(parameters) ⇒ Object
:nodoc:.
-
#port ⇒ Object
Returns the port number of this request as an integer.
-
#port_string ⇒ Object
Returns a port suffix like “:8080” if the port number of this request is not the default HTTP port 80 or HTTPS port 443.
-
#post? ⇒ Boolean
Is this a POST request? Equivalent to
request.method == :post
. -
#protocol ⇒ Object
Return ‘https://’ if this is an SSL request and ‘http://’ otherwise.
-
#put? ⇒ Boolean
Is this a PUT request? Equivalent to
request.method == :put
. -
#query_parameters ⇒ Object
:nodoc:.
-
#query_string ⇒ Object
Return the query string, accounting for server idiosyncracies.
-
#raw_post ⇒ Object
Read the request body.
-
#relative_url_root ⇒ Object
Returns the path minus the web server relative installation directory.
-
#remote_ip ⇒ Object
Determine originating IP address.
-
#request_method ⇒ Object
The true HTTP request method as a lowercase symbol, such as
:get
. -
#request_parameters ⇒ Object
:nodoc:.
-
#request_uri ⇒ Object
Return the request URI, accounting for server idiosyncracies.
-
#reset_session ⇒ Object
:nodoc:.
-
#server_software ⇒ Object
Returns the lowercase name of the HTTP server software.
-
#session ⇒ Object
:nodoc:.
-
#session=(session) ⇒ Object
:nodoc:.
-
#ssl? ⇒ Boolean
Is this an SSL request?.
-
#standard_port ⇒ Object
Returns the standard port number for this request’s protocol.
-
#subdomains(tld_length = 1) ⇒ Object
Returns all the subdomains as an array, so [“dev”, “www”] would be returned for “dev.www.rubyonrails.org”.
-
#symbolized_path_parameters ⇒ Object
The same as
path_parameters
with explicitly symbolized keys. -
#url ⇒ Object
Returns the complete URL used for this request.
-
#xml_http_request? ⇒ Boolean
(also: #xhr?)
Returns true if the request’s “X-Requested-With” header contains “XMLHttpRequest”.
Instance Attribute Details
#env ⇒ Object (readonly)
The hash of environment variables for this request, such as { ‘RAILS_ENV’ => ‘production’ }.
16 17 18 |
# File 'lib/action_controller/request.rb', line 16 def env @env end |
Class Method Details
.clean_up_ajax_request_body!(body) ⇒ Object
488 489 490 491 |
# File 'lib/action_controller/request.rb', line 488 def clean_up_ajax_request_body!(body) body.chop! if body[-1] == 0 body.gsub!(/&_=$/, '') end |
.extract_content_type_without_parameters(content_type_with_parameters) ⇒ Object
484 485 486 |
# File 'lib/action_controller/request.rb', line 484 def extract_content_type_without_parameters(content_type_with_parameters) $1.strip.downcase if content_type_with_parameters =~ /^([^,\;]*)/ end |
.extract_multipart_boundary(content_type_with_parameters) ⇒ Object
476 477 478 479 480 481 482 |
# File 'lib/action_controller/request.rb', line 476 def extract_multipart_boundary(content_type_with_parameters) if content_type_with_parameters =~ MULTIPART_BOUNDARY ['multipart/form-data', $1.dup] else extract_content_type_without_parameters(content_type_with_parameters) end end |
.parse_multipart_form_parameters(body, boundary, body_size, env) ⇒ Object
472 473 474 |
# File 'lib/action_controller/request.rb', line 472 def parse_multipart_form_parameters(body, boundary, body_size, env) parse_request_parameters(read_multipart(body, boundary, body_size, env)) end |
.parse_query_parameters(query_string) ⇒ Object
433 434 435 436 437 438 439 440 441 442 443 444 445 |
# File 'lib/action_controller/request.rb', line 433 def parse_query_parameters(query_string) return {} if query_string.blank? pairs = query_string.split('&').collect do |chunk| next if chunk.empty? key, value = chunk.split('=', 2) next if key.empty? value = value.nil? ? nil : CGI.unescape(value) [ CGI.unescape(key), value ] end.compact UrlEncodedPairParser.new(pairs).result end |
.parse_request_parameters(params) ⇒ Object
447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 |
# File 'lib/action_controller/request.rb', line 447 def parse_request_parameters(params) parser = UrlEncodedPairParser.new params = params.dup until params.empty? for key, value in params if key.blank? params.delete key elsif !key.include?('[') # much faster to test for the most common case first (GET) # and avoid the call to build_deep_hash parser.result[key] = get_typed_value(value[0]) params.delete key elsif value.is_a?(Array) parser.parse(key, get_typed_value(value.shift)) params.delete key if value.empty? else raise TypeError, "Expected array, found #{value.inspect}" end end end parser.result end |
Instance Method Details
#accepts ⇒ Object
Returns the accepted MIME type for the request
83 84 85 86 87 88 89 90 |
# File 'lib/action_controller/request.rb', line 83 def accepts @accepts ||= if @env['HTTP_ACCEPT'].to_s.strip.empty? [ content_type, Mime::ALL ].compact # make sure content_type being nil is not included else Mime::Type.parse(@env['HTTP_ACCEPT']) end end |
#body ⇒ Object
The request body is an IO input stream.
336 337 |
# File 'lib/action_controller/request.rb', line 336 def body end |
#content_length ⇒ Object
70 71 72 |
# File 'lib/action_controller/request.rb', line 70 def content_length @content_length ||= env['CONTENT_LENGTH'].to_i end |
#content_type ⇒ Object
The MIME type of the HTTP request, such as Mime::XML.
For backward compatibility, the post format is extracted from the X-Post-Data-Format HTTP header if present.
78 79 80 |
# File 'lib/action_controller/request.rb', line 78 def content_type @content_type ||= Mime::Type.lookup(content_type_without_parameters) end |
#cookies ⇒ Object
:nodoc:
345 346 |
# File 'lib/action_controller/request.rb', line 345 def #:nodoc: end |
#delete? ⇒ Boolean
Is this a DELETE request? Equivalent to request.method == :delete
.
54 55 56 |
# File 'lib/action_controller/request.rb', line 54 def delete? request_method == :delete end |
#domain(tld_length = 1) ⇒ Object
Returns the domain part of a host, such as rubyonrails.org in “www.rubyonrails.org”. You can specify a different tld_length
, such as 2 to catch rubyonrails.co.uk in “www.rubyonrails.co.uk”.
222 223 224 225 226 |
# File 'lib/action_controller/request.rb', line 222 def domain(tld_length = 1) return nil unless named_host?(host) host.split('.').last(1 + tld_length).join('.') end |
#format ⇒ Object
Returns the Mime type for the format used in the request. If there is no format available, the first of the accept types will be used. Examples:
GET /posts/5.xml | request.format => Mime::XML
GET /posts/5.xhtml | request.format => Mime::HTML
GET /posts/5 | request.format => request.accepts.first (usually Mime::HTML for browsers)
98 99 100 |
# File 'lib/action_controller/request.rb', line 98 def format @format ||= parameters[:format] ? Mime::Type.lookup_by_extension(parameters[:format]) : accepts.first end |
#format=(extension) ⇒ Object
Sets the format by string extension, which can be used to force custom formats that are not controlled by the extension. Example:
class ApplicationController < ActionController::Base
before_filter :adjust_format_for_iphone
private
def adjust_format_for_iphone
request.format = :iphone if request.env["HTTP_USER_AGENT"][/iPhone/]
end
end
114 115 116 117 |
# File 'lib/action_controller/request.rb', line 114 def format=(extension) parameters[:format] = extension.to_s @format = Mime::Type.lookup_by_extension(parameters[:format]) end |
#get? ⇒ Boolean
Is this a GET (or HEAD) request? Equivalent to request.method == :get
.
39 40 41 |
# File 'lib/action_controller/request.rb', line 39 def get? method == :get end |
#head? ⇒ Boolean
Is this a HEAD request? request.method
sees HEAD as :get
, so check the HTTP method directly.
60 61 62 |
# File 'lib/action_controller/request.rb', line 60 def head? request_method == :head end |
#headers ⇒ Object
Provides acccess to the request’s HTTP headers, for example:
request.headers["Content-Type"] # => "text/plain"
66 67 68 |
# File 'lib/action_controller/request.rb', line 66 def headers @headers ||= ActionController::Http::Headers.new(@env) end |
#host ⇒ Object
Returns the host for this request, such as example.com.
192 193 |
# File 'lib/action_controller/request.rb', line 192 def host end |
#host_with_port ⇒ Object
Returns a host:port string for this request, such as example.com or example.com:8080.
197 198 199 |
# File 'lib/action_controller/request.rb', line 197 def host_with_port @host_with_port ||= host + port_string end |
#method ⇒ Object
The HTTP request method as a lowercase symbol, such as :get
. Note, HEAD is returned as :get
since the two are functionally equivalent from the application’s perspective.
34 35 36 |
# File 'lib/action_controller/request.rb', line 34 def method request_method == :head ? :get : request_method end |
#parameters ⇒ Object
Returns both GET and POST parameters in a single hash.
306 307 308 |
# File 'lib/action_controller/request.rb', line 306 def parameters @parameters ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access end |
#path ⇒ Object
Returns the interpreted path to requested resource after all the installation directory of this application was taken into account
271 272 273 274 275 276 277 |
# File 'lib/action_controller/request.rb', line 271 def path path = (uri = request_uri) ? uri.split('?').first.to_s : '' # Cut off the path to the installation directory if given path.sub!(%r/^#{relative_url_root}/, '') path || '' end |
#path_parameters ⇒ Object
Returns a hash with the parameters used to form the path of the request. Returned hash keys are strings. See symbolized_path_parameters
for symbolized keys.
Example:
{'action' => 'my_action', 'controller' => 'my_controller'}
326 327 328 |
# File 'lib/action_controller/request.rb', line 326 def path_parameters @path_parameters ||= {} end |
#path_parameters=(parameters) ⇒ Object
:nodoc:
310 311 312 313 |
# File 'lib/action_controller/request.rb', line 310 def path_parameters=(parameters) #:nodoc: @path_parameters = parameters @symbolized_path_parameters = @parameters = nil end |
#port ⇒ Object
Returns the port number of this request as an integer.
202 203 204 |
# File 'lib/action_controller/request.rb', line 202 def port @port_as_int ||= @env['SERVER_PORT'].to_i end |
#port_string ⇒ Object
Returns a port suffix like “:8080” if the port number of this request is not the default HTTP port 80 or HTTPS port 443.
216 217 218 |
# File 'lib/action_controller/request.rb', line 216 def port_string (port == standard_port) ? '' : ":#{port}" end |
#post? ⇒ Boolean
Is this a POST request? Equivalent to request.method == :post
.
44 45 46 |
# File 'lib/action_controller/request.rb', line 44 def post? request_method == :post end |
#protocol ⇒ Object
Return ‘https://’ if this is an SSL request and ‘http://’ otherwise.
182 183 184 |
# File 'lib/action_controller/request.rb', line 182 def protocol ssl? ? 'https://' : 'http://' end |
#put? ⇒ Boolean
Is this a PUT request? Equivalent to request.method == :put
.
49 50 51 |
# File 'lib/action_controller/request.rb', line 49 def put? request_method == :put end |
#query_parameters ⇒ Object
:nodoc:
339 340 |
# File 'lib/action_controller/request.rb', line 339 def query_parameters #:nodoc: end |
#query_string ⇒ Object
Return the query string, accounting for server idiosyncracies.
238 239 240 241 242 243 244 |
# File 'lib/action_controller/request.rb', line 238 def query_string if uri = @env['REQUEST_URI'] uri.split('?', 2)[1] || '' else @env['QUERY_STRING'] || '' end end |
#raw_post ⇒ Object
Read the request body. This is useful for web services that need to work with raw requests directly.
297 298 299 300 301 302 303 |
# File 'lib/action_controller/request.rb', line 297 def raw_post unless env.include? 'RAW_POST_DATA' env['RAW_POST_DATA'] = body.read(content_length) body.rewind if body.respond_to?(:rewind) end env['RAW_POST_DATA'] end |
#relative_url_root ⇒ Object
Returns the path minus the web server relative installation directory. This can be set with the environment variable RAILS_RELATIVE_URL_ROOT. It can be automatically extracted for Apache setups. If the server is not Apache, this method returns an empty string.
283 284 285 286 287 288 289 290 291 292 |
# File 'lib/action_controller/request.rb', line 283 def relative_url_root @@relative_url_root ||= case when @env["RAILS_RELATIVE_URL_ROOT"] @env["RAILS_RELATIVE_URL_ROOT"] when server_software == 'apache' @env["SCRIPT_NAME"].to_s.sub(/\/dispatch\.(fcgi|rb|cgi)$/, '') else '' end end |
#remote_ip ⇒ Object
Determine originating IP address. REMOTE_ADDR is the standard but will fail if the user is behind a proxy. HTTP_CLIENT_IP and/or HTTP_X_FORWARDED_FOR are set by proxies so check for these if REMOTE_ADDR is a proxy. HTTP_X_FORWARDED_FOR may be a comma- delimited list in the case of multiple chained proxies; the last address which is not trusted is the originating IP.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 |
# File 'lib/action_controller/request.rb', line 137 def remote_ip remote_addr_list = @env['REMOTE_ADDR'] && @env['REMOTE_ADDR'].split(',').collect(&:strip) unless remote_addr_list.blank? not_trusted_addrs = remote_addr_list.reject {|addr| addr =~ TRUSTED_PROXIES} return not_trusted_addrs.first unless not_trusted_addrs.empty? end remote_ips = @env['HTTP_X_FORWARDED_FOR'] && @env['HTTP_X_FORWARDED_FOR'].split(',') if @env.include? 'HTTP_CLIENT_IP' if remote_ips && !remote_ips.include?(@env['HTTP_CLIENT_IP']) # We don't know which came from the proxy, and which from the user raise ActionControllerError.new(<<EOM) IP spoofing attack?! HTTP_CLIENT_IP=#{@env['HTTP_CLIENT_IP'].inspect} HTTP_X_FORWARDED_FOR=#{@env['HTTP_X_FORWARDED_FOR'].inspect} EOM end return @env['HTTP_CLIENT_IP'] end if remote_ips while remote_ips.size > 1 && TRUSTED_PROXIES =~ remote_ips.last.strip remote_ips.pop end return remote_ips.last.strip end @env['REMOTE_ADDR'] end |
#request_method ⇒ Object
The true HTTP request method as a lowercase symbol, such as :get
. UnknownHttpMethod is raised for invalid methods not listed in ACCEPTED_HTTP_METHODS.
20 21 22 23 24 25 26 27 28 29 |
# File 'lib/action_controller/request.rb', line 20 def request_method @request_method ||= begin method = ((@env['REQUEST_METHOD'] == 'POST' && !parameters[:_method].blank?) ? parameters[:_method].to_s : @env['REQUEST_METHOD']).downcase if ACCEPTED_HTTP_METHODS.include?(method) method.to_sym else raise UnknownHttpMethod, "#{method}, accepted HTTP methods are #{ACCEPTED_HTTP_METHODS.to_a.to_sentence}" end end end |
#request_parameters ⇒ Object
:nodoc:
342 343 |
# File 'lib/action_controller/request.rb', line 342 def request_parameters #:nodoc: end |
#request_uri ⇒ Object
Return the request URI, accounting for server idiosyncracies. WEBrick includes the full URL. IIS leaves REQUEST_URI blank.
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 |
# File 'lib/action_controller/request.rb', line 248 def request_uri if uri = @env['REQUEST_URI'] # Remove domain, which webrick puts into the request_uri. (%r{^\w+\://[^/]+(/.*|$)$} =~ uri) ? $1 : uri else # Construct IIS missing REQUEST_URI from SCRIPT_NAME and PATH_INFO. script_filename = @env['SCRIPT_NAME'].to_s.match(%r{[^/]+$}) uri = @env['PATH_INFO'] uri = uri.sub(/#{script_filename}\//, '') unless script_filename.nil? unless (env_qs = @env['QUERY_STRING']).nil? || env_qs.empty? uri << '?' << env_qs end if uri.nil? @env.delete('REQUEST_URI') uri else @env['REQUEST_URI'] = uri end end end |
#reset_session ⇒ Object
:nodoc:
355 356 |
# File 'lib/action_controller/request.rb', line 355 def reset_session #:nodoc: end |
#server_software ⇒ Object
Returns the lowercase name of the HTTP server software.
171 172 173 |
# File 'lib/action_controller/request.rb', line 171 def server_software (@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil end |
#session ⇒ Object
:nodoc:
348 349 |
# File 'lib/action_controller/request.rb', line 348 def session #:nodoc: end |
#session=(session) ⇒ Object
:nodoc:
351 352 353 |
# File 'lib/action_controller/request.rb', line 351 def session=(session) #:nodoc: @session = session end |
#ssl? ⇒ Boolean
Is this an SSL request?
187 188 189 |
# File 'lib/action_controller/request.rb', line 187 def ssl? @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https' end |
#standard_port ⇒ Object
Returns the standard port number for this request’s protocol
207 208 209 210 211 212 |
# File 'lib/action_controller/request.rb', line 207 def standard_port case protocol when 'https://' then 443 else 80 end end |
#subdomains(tld_length = 1) ⇒ Object
Returns all the subdomains as an array, so [“dev”, “www”] would be returned for “dev.www.rubyonrails.org”. You can specify a different tld_length
, such as 2 to catch [“www”] instead of [“www”, “rubyonrails”] in “www.rubyonrails.co.uk”.
231 232 233 234 235 |
# File 'lib/action_controller/request.rb', line 231 def subdomains(tld_length = 1) return [] unless named_host?(host) parts = host.split('.') parts[0..-(tld_length+2)] end |
#symbolized_path_parameters ⇒ Object
The same as path_parameters
with explicitly symbolized keys
316 317 318 |
# File 'lib/action_controller/request.rb', line 316 def symbolized_path_parameters @symbolized_path_parameters ||= path_parameters.symbolize_keys end |
#url ⇒ Object
Returns the complete URL used for this request
177 178 179 |
# File 'lib/action_controller/request.rb', line 177 def url protocol + host_with_port + request_uri end |
#xml_http_request? ⇒ Boolean Also known as: xhr?
Returns true if the request’s “X-Requested-With” header contains “XMLHttpRequest”. (The Prototype Javascript library sends this header with every Ajax request.)
122 123 124 |
# File 'lib/action_controller/request.rb', line 122 def xml_http_request? !(@env['HTTP_X_REQUESTED_WITH'] !~ /XMLHttpRequest/i) end |