Class: Rack::Request

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

Overview

Rack::Request provides a convenient interface to a Rack environment. It is stateless, the environment env passed to the constructor will be directly modified.

req = Rack::Request.new(env)
req.post?
req.params["data"]

Constant Summary collapse

FORM_DATA_MEDIA_TYPES =

The set of form-data media-types. Requests that do not indicate one of the media types presents in this list will not be eligible for form-data / param parsing.

[
  'application/x-www-form-urlencoded',
  'multipart/form-data'
]
PARSEABLE_DATA_MEDIA_TYPES =

The set of media-types. Requests that do not indicate one of the media types presents in this list will not be eligible for param parsing like soap attachments or generic multiparts

[
  'multipart/related',
  'multipart/mixed'
]
DEFAULT_PORTS =

Default ports depending on scheme. Used to decide whether or not to include the port in a generated URI.

{ 'http' => 80, 'https' => 443, 'coffee' => 80 }

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(env) ⇒ Request

Returns a new instance of Request.



16
17
18
# File 'lib/rack/request.rb', line 16

def initialize(env)
  @env = env
end

Instance Attribute Details

#envObject (readonly)

The environment of the request.



14
15
16
# File 'lib/rack/request.rb', line 14

def env
  @env
end

Instance Method Details

#[](key) ⇒ Object

shortcut for request.params



269
270
271
# File 'lib/rack/request.rb', line 269

def [](key)
  params[key.to_s]
end

#[]=(key, value) ⇒ Object

shortcut for request.params = value

Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.



276
277
278
# File 'lib/rack/request.rb', line 276

def []=(key, value)
  params[key.to_s] = value
end

#accept_encodingObject



336
337
338
# File 'lib/rack/request.rb', line 336

def accept_encoding
  parse_http_accept_header(@env["HTTP_ACCEPT_ENCODING"])
end

#accept_languageObject



340
341
342
# File 'lib/rack/request.rb', line 340

def accept_language
  parse_http_accept_header(@env["HTTP_ACCEPT_LANGUAGE"])
end

#base_urlObject



317
318
319
320
321
# File 'lib/rack/request.rb', line 317

def base_url
  url = "#{scheme}://#{host}"
  url << ":#{port}" if port != DEFAULT_PORTS[scheme]
  url
end

#bodyObject



20
# File 'lib/rack/request.rb', line 20

def body;            @env["rack.input"]                       end

#content_charsetObject

The character set of the request body if a “charset” media type parameter was given, or nil if no “charset” was specified. Note that, per RFC2616, text/* media types that specify no explicit charset are to be considered ISO-8859-1.



62
63
64
# File 'lib/rack/request.rb', line 62

def content_charset
  media_type_params['charset']
end

#content_lengthObject



25
# File 'lib/rack/request.rb', line 25

def content_length;  @env['CONTENT_LENGTH']                   end

#content_typeObject



27
28
29
30
# File 'lib/rack/request.rb', line 27

def content_type
  content_type = @env['CONTENT_TYPE']
  content_type.nil? || content_type.empty? ? nil : content_type
end

#cookiesObject



295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/rack/request.rb', line 295

def cookies
  hash   = @env["rack.request.cookie_hash"] ||= {}
  string = @env["HTTP_COOKIE"]

  return hash if string == @env["rack.request.cookie_string"]
  hash.clear

  # According to RFC 2109:
  #   If multiple cookies satisfy the criteria above, they are ordered in
  #   the Cookie header such that those with more specific Path attributes
  #   precede those with less specific.  Ordering with respect to other
  #   attributes (e.g., Domain) is unspecified.
  cookies = Utils.parse_query(string, ';,') { |s| Rack::Utils.unescape(s) rescue s }
  cookies.each { |k,v| hash[k] = Array === v ? v.first : v }
  @env["rack.request.cookie_string"] = string
  hash
end

#delete?Boolean

Checks the HTTP request method (or verb) to see if it was of type DELETE

Returns:

  • (Boolean)


116
# File 'lib/rack/request.rb', line 116

def delete?;  request_method == "DELETE"  end

#delete_param(k) ⇒ Object

Destructively delete a parameter, whether it’s in GET or POST. Returns the value of the deleted parameter.

If the parameter is in both GET and POST, the POST value takes precedence since that’s how #params works.

env is not touched.



262
263
264
265
266
# File 'lib/rack/request.rb', line 262

def delete_param(k)
  v = [ self.POST.delete(k), self.GET.delete(k) ].compact.first
  @params = nil
  v
end

#form_data?Boolean

Determine whether the request body contains form-data by checking the request Content-Type for one of the media-types: “application/x-www-form-urlencoded” or “multipart/form-data”. The list of form-data media types can be modified through the FORM_DATA_MEDIA_TYPES array.

A request body is also assumed to contain form-data when no Content-Type header is provided and the request_method is POST.

Returns:

  • (Boolean)


174
175
176
177
178
# File 'lib/rack/request.rb', line 174

def form_data?
  type = media_type
  meth = env["rack.methodoverride.original_method"] || env[REQUEST_METHOD]
  (meth == 'POST' && type.nil?) || FORM_DATA_MEDIA_TYPES.include?(type)
end

#fullpathObject



332
333
334
# File 'lib/rack/request.rb', line 332

def fullpath
  query_string.empty? ? path : "#{path}?#{query_string}"
end

#GETObject

Returns the data received in the query string.



187
188
189
190
191
192
193
194
195
# File 'lib/rack/request.rb', line 187

def GET
  if @env["rack.request.query_string"] == query_string
    @env["rack.request.query_hash"]
  else
    p = parse_query(query_string)
    @env["rack.request.query_string"] = query_string
    @env["rack.request.query_hash"]   = p
  end
end

#get?Boolean

Checks the HTTP request method (or verb) to see if it was of type GET

Returns:

  • (Boolean)


119
# File 'lib/rack/request.rb', line 119

def get?;     request_method == GET       end

#head?Boolean

Checks the HTTP request method (or verb) to see if it was of type HEAD

Returns:

  • (Boolean)


122
# File 'lib/rack/request.rb', line 122

def head?;    request_method == HEAD      end

#hostObject



106
107
108
109
# File 'lib/rack/request.rb', line 106

def host
  # Remove port number.
  host_with_port.to_s.sub(/:\d+\z/, '')
end

#host_with_portObject



84
85
86
87
88
89
90
# File 'lib/rack/request.rb', line 84

def host_with_port
  if forwarded = @env["HTTP_X_FORWARDED_HOST"]
    forwarded.split(/,\s?/).last
  else
    @env['HTTP_HOST'] || "#{@env['SERVER_NAME'] || @env['SERVER_ADDR']}:#{@env['SERVER_PORT']}"
  end
end

#ipObject



348
349
350
351
352
353
354
355
356
357
# File 'lib/rack/request.rb', line 348

def ip
  remote_addrs = split_ip_addresses(@env['REMOTE_ADDR'])
  remote_addrs = reject_trusted_ip_addresses(remote_addrs)

  return remote_addrs.first if remote_addrs.any?

  forwarded_ips = split_ip_addresses(@env['HTTP_X_FORWARDED_FOR'])

  return reject_trusted_ip_addresses(forwarded_ips).last || @env["REMOTE_ADDR"]
end

#link?Boolean

Checks the HTTP request method (or verb) to see if it was of type LINK

Returns:

  • (Boolean)


128
# File 'lib/rack/request.rb', line 128

def link?;    request_method == "LINK"    end

#loggerObject



34
# File 'lib/rack/request.rb', line 34

def logger;          @env['rack.logger']                      end

#media_typeObject

The media type (type/subtype) portion of the CONTENT_TYPE header without any media type parameters. e.g., when CONTENT_TYPE is “text/plain;charset=utf-8”, the media-type is “text/plain”.

For more information on the use of media types in HTTP, see: www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7



42
43
44
# File 'lib/rack/request.rb', line 42

def media_type
  content_type && content_type.split(/\s*[;,]\s*/, 2).first.downcase
end

#media_type_paramsObject

The media type parameters provided in CONTENT_TYPE as a Hash, or an empty Hash if no CONTENT_TYPE or media-type parameters were provided. e.g., when the CONTENT_TYPE is “text/plain;charset=utf-8”, this method responds with the following Hash:

{ 'charset' => 'utf-8' }


51
52
53
54
55
56
# File 'lib/rack/request.rb', line 51

def media_type_params
  return {} if content_type.nil?
  Hash[*content_type.split(/\s*[;,]\s*/)[1..-1].
    collect { |s| s.split('=', 2) }.
    map { |k,v| [k.downcase, strip_doublequotes(v)] }.flatten]
end

#options?Boolean

Checks the HTTP request method (or verb) to see if it was of type OPTIONS

Returns:

  • (Boolean)


125
# File 'lib/rack/request.rb', line 125

def options?; request_method == "OPTIONS" end

#paramsObject

The union of GET and POST data.

Note that modifications will not be persisted in the env. Use update_param or delete_param if you want to destructively modify params.



229
230
231
232
233
# File 'lib/rack/request.rb', line 229

def params
  @params ||= self.GET.merge(self.POST)
rescue EOFError
  self.GET.dup
end

#parseable_data?Boolean

Determine whether the request body contains data by checking the request media_type against registered parse-data media-types

Returns:

  • (Boolean)


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

def parseable_data?
  PARSEABLE_DATA_MEDIA_TYPES.include?(media_type)
end

#patch?Boolean

Checks the HTTP request method (or verb) to see if it was of type PATCH

Returns:

  • (Boolean)


131
# File 'lib/rack/request.rb', line 131

def patch?;   request_method == "PATCH"   end

#pathObject



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

def path
  script_name + path_info
end

#path_infoObject



22
# File 'lib/rack/request.rb', line 22

def path_info;       @env[PATH_INFO].to_s                     end

#path_info=(s) ⇒ Object



112
# File 'lib/rack/request.rb', line 112

def path_info=(s);   @env["PATH_INFO"] = s.to_s               end

#portObject



92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/rack/request.rb', line 92

def port
  if port = host_with_port.split(/:/)[1]
    port.to_i
  elsif port = @env['HTTP_X_FORWARDED_PORT']
    port.to_i
  elsif @env.has_key?("HTTP_X_FORWARDED_HOST")
    DEFAULT_PORTS[scheme]
  elsif @env.has_key?("HTTP_X_FORWARDED_PROTO")
    DEFAULT_PORTS[@env['HTTP_X_FORWARDED_PROTO'].split(',')[0]]
  else
    @env["SERVER_PORT"].to_i
  end
end

#POSTObject

Returns the data received in the request body.

This method support both application/x-www-form-urlencoded and multipart/form-data.



201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
# File 'lib/rack/request.rb', line 201

def POST
  if @env["rack.input"].nil?
    raise "Missing rack.input"
  elsif @env["rack.request.form_input"].equal? @env["rack.input"]
    @env["rack.request.form_hash"]
  elsif form_data? || parseable_data?
    unless @env["rack.request.form_hash"] = parse_multipart(env)
      form_vars = @env["rack.input"].read

      # Fix for Safari Ajax postings that always append \0
      # form_vars.sub!(/\0\z/, '') # performance replacement:
      form_vars.slice!(-1) if form_vars[-1] == ?\0

      @env["rack.request.form_vars"] = form_vars
      @env["rack.request.form_hash"] = parse_query(form_vars)

      @env["rack.input"].rewind
    end
    @env["rack.request.form_input"] = @env["rack.input"]
    @env["rack.request.form_hash"]
  else
    {}
  end
end

#post?Boolean

Checks the HTTP request method (or verb) to see if it was of type POST

Returns:

  • (Boolean)


134
# File 'lib/rack/request.rb', line 134

def post?;    request_method == "POST"    end

#put?Boolean

Checks the HTTP request method (or verb) to see if it was of type PUT

Returns:

  • (Boolean)


137
# File 'lib/rack/request.rb', line 137

def put?;     request_method == "PUT"     end

#query_stringObject



24
# File 'lib/rack/request.rb', line 24

def query_string;    @env[QUERY_STRING].to_s                  end

#refererObject Also known as: referrer

the referer of the client



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

def referer
  @env['HTTP_REFERER']
end

#request_methodObject



23
# File 'lib/rack/request.rb', line 23

def request_method;  @env["REQUEST_METHOD"]                   end

#schemeObject



66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/rack/request.rb', line 66

def scheme
  if @env['HTTPS'] == 'on'
    'https'
  elsif @env['HTTP_X_FORWARDED_SSL'] == 'on'
    'https'
  elsif @env['HTTP_X_FORWARDED_SCHEME']
    @env['HTTP_X_FORWARDED_SCHEME']
  elsif @env['HTTP_X_FORWARDED_PROTO']
    @env['HTTP_X_FORWARDED_PROTO'].split(',')[0]
  else
    @env["rack.url_scheme"]
  end
end

#script_nameObject



21
# File 'lib/rack/request.rb', line 21

def script_name;     @env[SCRIPT_NAME].to_s                   end

#script_name=(s) ⇒ Object



111
# File 'lib/rack/request.rb', line 111

def script_name=(s); @env["SCRIPT_NAME"] = s.to_s             end

#sessionObject



32
# File 'lib/rack/request.rb', line 32

def session;         @env['rack.session'] ||= {}              end

#session_optionsObject



33
# File 'lib/rack/request.rb', line 33

def session_options; @env['rack.session.options'] ||= {}      end

#ssl?Boolean

Returns:

  • (Boolean)


80
81
82
# File 'lib/rack/request.rb', line 80

def ssl?
  scheme == 'https'
end

#trace?Boolean

Checks the HTTP request method (or verb) to see if it was of type TRACE

Returns:

  • (Boolean)


140
# File 'lib/rack/request.rb', line 140

def trace?;   request_method == "TRACE"   end

#trusted_proxy?(ip) ⇒ Boolean

Returns:

  • (Boolean)


344
345
346
# File 'lib/rack/request.rb', line 344

def trusted_proxy?(ip)
  ip =~ /\A127\.0\.0\.1\Z|\A(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\.|\A::1\Z|\Afd[0-9a-f]{2}:.+|\Alocalhost\Z|\Aunix\Z|\Aunix:/i
end

#unlink?Boolean

Checks the HTTP request method (or verb) to see if it was of type UNLINK

Returns:

  • (Boolean)


143
# File 'lib/rack/request.rb', line 143

def unlink?;  request_method == "UNLINK"  end

#update_param(k, v) ⇒ Object

Destructively update a parameter, whether it’s in GET and/or POST. Returns nil.

The parameter is updated wherever it was previous defined, so GET, POST, or both. If it wasn’t previously defined, it’s inserted into GET.

env is not touched.



240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
# File 'lib/rack/request.rb', line 240

def update_param(k, v)
  found = false
  if self.GET.has_key?(k)
    found = true
    self.GET[k] = v
  end
  if self.POST.has_key?(k)
    found = true
    self.POST[k] = v
  end
  unless found
    self.GET[k] = v
  end
  @params = nil
  nil
end

#urlObject

Tries to return a remake of the original request URL as a string.



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

def url
  base_url + fullpath
end

#user_agentObject



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

def user_agent
  @env['HTTP_USER_AGENT']
end

#values_at(*keys) ⇒ Object

like Hash#values_at



281
282
283
# File 'lib/rack/request.rb', line 281

def values_at(*keys)
  keys.map{|key| params[key] }
end

#xhr?Boolean

Returns:

  • (Boolean)


313
314
315
# File 'lib/rack/request.rb', line 313

def xhr?
  @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest"
end