Class: ActionController::AbstractRequest

Inherits:
Object
  • Object
show all
Defined in:
lib/action_controller/request.rb

Overview

CgiRequest and TestRequest provide concrete implementations.

Direct Known Subclasses

CgiRequest, TestRequest

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#envObject (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



460
461
462
463
# File 'lib/action_controller/request.rb', line 460

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



456
457
458
# File 'lib/action_controller/request.rb', line 456

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



448
449
450
451
452
453
454
# File 'lib/action_controller/request.rb', line 448

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, content_length, env) ⇒ Object



444
445
446
# File 'lib/action_controller/request.rb', line 444

def parse_multipart_form_parameters(body, boundary, content_length, env)
  parse_request_parameters(read_multipart(body, boundary, content_length, env))
end

.parse_query_parameters(query_string) ⇒ Object



405
406
407
408
409
410
411
412
413
414
415
416
417
# File 'lib/action_controller/request.rb', line 405

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



419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'lib/action_controller/request.rb', line 419

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

#acceptsObject

Returns the accepted MIME type for the request



81
82
83
84
85
86
87
88
# File 'lib/action_controller/request.rb', line 81

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

#bodyObject

The request body is an IO input stream.



316
317
# File 'lib/action_controller/request.rb', line 316

def body
end

#content_lengthObject



68
69
70
# File 'lib/action_controller/request.rb', line 68

def content_length
  @content_length ||= env['CONTENT_LENGTH'].to_i
end

#content_typeObject

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.



76
77
78
# File 'lib/action_controller/request.rb', line 76

def content_type
  @content_type ||= Mime::Type.lookup(content_type_without_parameters)
end

#cookiesObject

:nodoc:



325
326
# File 'lib/action_controller/request.rb', line 325

def cookies #:nodoc:
end

#delete?Boolean

Is this a DELETE request? Equivalent to request.method == :delete

Returns:

  • (Boolean)


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”.



202
203
204
205
206
# File 'lib/action_controller/request.rb', line 202

def domain(tld_length = 1)
  return nil unless named_host?(host)

  host.split('.').last(1 + tld_length).join('.')
end

#formatObject

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)


96
97
98
# File 'lib/action_controller/request.rb', line 96

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


112
113
114
115
# File 'lib/action_controller/request.rb', line 112

def format=(extension)
  parameters[:format] = extension.to_s
  format
end

#get?Boolean

Is this a GET (or HEAD) request? Equivalent to request.method == :get

Returns:

  • (Boolean)


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.

Returns:

  • (Boolean)


60
61
62
# File 'lib/action_controller/request.rb', line 60

def head?
  request_method == :head
end

#headersObject



64
65
66
# File 'lib/action_controller/request.rb', line 64

def headers
  @env
end

#hostObject

Returns the host for this request, such as example.com.



172
173
# File 'lib/action_controller/request.rb', line 172

def host
end

#host_with_portObject

Returns a host:port string for this request, such as example.com or example.com:8080.



177
178
179
# File 'lib/action_controller/request.rb', line 177

def host_with_port
  @host_with_port ||= host + port_string
end

#methodObject

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

#parametersObject

Returns both GET and POST parameters in a single hash.



286
287
288
# File 'lib/action_controller/request.rb', line 286

def parameters
  @parameters ||= request_parameters.merge(query_parameters).update(path_parameters).with_indifferent_access
end

#pathObject

Returns the interpreted path to requested resource after all the installation directory of this application was taken into account



251
252
253
254
255
256
257
# File 'lib/action_controller/request.rb', line 251

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_parametersObject

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'}


306
307
308
# File 'lib/action_controller/request.rb', line 306

def path_parameters
  @path_parameters ||= {}
end

#path_parameters=(parameters) ⇒ Object

:nodoc:



290
291
292
293
# File 'lib/action_controller/request.rb', line 290

def path_parameters=(parameters) #:nodoc:
  @path_parameters = parameters
  @symbolized_path_parameters = @parameters = nil
end

#portObject

Returns the port number of this request as an integer.



182
183
184
# File 'lib/action_controller/request.rb', line 182

def port
  @port_as_int ||= @env['SERVER_PORT'].to_i
end

#port_stringObject

Returns a port suffix like “:8080” if the port number of this request is not the default HTTP port 80 or HTTPS port 443.



196
197
198
# File 'lib/action_controller/request.rb', line 196

def port_string
  (port == standard_port) ? '' : ":#{port}"
end

#post?Boolean

Is this a POST request? Equivalent to request.method == :post

Returns:

  • (Boolean)


44
45
46
# File 'lib/action_controller/request.rb', line 44

def post?
  request_method == :post
end

#protocolObject

Return ‘https://’ if this is an SSL request and ‘http://’ otherwise.



162
163
164
# File 'lib/action_controller/request.rb', line 162

def protocol
  ssl? ? 'https://' : 'http://'
end

#put?Boolean

Is this a PUT request? Equivalent to request.method == :put

Returns:

  • (Boolean)


49
50
51
# File 'lib/action_controller/request.rb', line 49

def put?
  request_method == :put
end

#query_parametersObject

:nodoc:



319
320
# File 'lib/action_controller/request.rb', line 319

def query_parameters #:nodoc:
end

#query_stringObject

Return the query string, accounting for server idiosyncracies.



218
219
220
221
222
223
224
# File 'lib/action_controller/request.rb', line 218

def query_string
  if uri = @env['REQUEST_URI']
    uri.split('?', 2)[1] || ''
  else
    @env['QUERY_STRING'] || ''
  end
end

#raw_postObject

Read the request body. This is useful for web services that need to work with raw requests directly.



277
278
279
280
281
282
283
# File 'lib/action_controller/request.rb', line 277

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_rootObject

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.



263
264
265
266
267
268
269
270
271
272
# File 'lib/action_controller/request.rb', line 263

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_ipObject

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 before falling back to REMOTE_ADDR. HTTP_X_FORWARDED_FOR may be a comma- delimited list in the case of multiple chained proxies; the first is the originating IP.

Security note: do not use if IP spoofing is a concern for your application. Since remote_ip checks HTTP headers for addresses forwarded by proxies, the client may send any IP. remote_addr can’t be spoofed but also doesn’t work behind a proxy, since it’s always the proxy’s IP.



136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/action_controller/request.rb', line 136

def remote_ip
  return @env['HTTP_CLIENT_IP'] if @env.include? 'HTTP_CLIENT_IP'

  if @env.include? 'HTTP_X_FORWARDED_FOR' then
    remote_ips = @env['HTTP_X_FORWARDED_FOR'].split(',').reject do |ip|
      ip.strip =~ /^unknown$|^(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\./i
    end

    return remote_ips.first.strip unless remote_ips.empty?
  end

  @env['REMOTE_ADDR']
end

#request_methodObject

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_parametersObject

:nodoc:



322
323
# File 'lib/action_controller/request.rb', line 322

def request_parameters #:nodoc:
end

#request_uriObject

Return the request URI, accounting for server idiosyncracies. WEBrick includes the full URL. IIS leaves REQUEST_URI blank.



228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
# File 'lib/action_controller/request.rb', line 228

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_sessionObject

:nodoc:



335
336
# File 'lib/action_controller/request.rb', line 335

def reset_session #:nodoc:
end

#server_softwareObject

Returns the lowercase name of the HTTP server software.



151
152
153
# File 'lib/action_controller/request.rb', line 151

def server_software
  (@env['SERVER_SOFTWARE'] && /^([a-zA-Z]+)/ =~ @env['SERVER_SOFTWARE']) ? $1.downcase : nil
end

#sessionObject

:nodoc:



328
329
# File 'lib/action_controller/request.rb', line 328

def session #:nodoc:
end

#session=(session) ⇒ Object

:nodoc:



331
332
333
# File 'lib/action_controller/request.rb', line 331

def session=(session) #:nodoc:
  @session = session
end

#ssl?Boolean

Is this an SSL request?

Returns:

  • (Boolean)


167
168
169
# File 'lib/action_controller/request.rb', line 167

def ssl?
  @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
end

#standard_portObject

Returns the standard port number for this request’s protocol



187
188
189
190
191
192
# File 'lib/action_controller/request.rb', line 187

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”.



211
212
213
214
215
# File 'lib/action_controller/request.rb', line 211

def subdomains(tld_length = 1)
  return [] unless named_host?(host)
  parts = host.split('.')
  parts[0..-(tld_length+2)]
end

#symbolized_path_parametersObject

The same as path_parameters with explicitly symbolized keys



296
297
298
# File 'lib/action_controller/request.rb', line 296

def symbolized_path_parameters 
  @symbolized_path_parameters ||= path_parameters.symbolize_keys
end

#urlObject

Returns the complete URL used for this request



157
158
159
# File 'lib/action_controller/request.rb', line 157

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.)

Returns:

  • (Boolean)


120
121
122
# File 'lib/action_controller/request.rb', line 120

def xml_http_request?
  !(@env['HTTP_X_REQUESTED_WITH'] !~ /XMLHttpRequest/i)
end