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.



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

def initialize(env)
  @env = env
end

Instance Attribute Details

#envObject (readonly)

The environment of the request.



12
13
14
# File 'lib/rack/request.rb', line 12

def env
  @env
end

Instance Method Details

#[](key) ⇒ Object

shortcut for request.params[key]



267
268
269
# File 'lib/rack/request.rb', line 267

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

#[]=(key, value) ⇒ Object

shortcut for request.params[key] = value

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



274
275
276
# File 'lib/rack/request.rb', line 274

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

#accept_encodingObject



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

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

#accept_languageObject



338
339
340
# File 'lib/rack/request.rb', line 338

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

#base_urlObject



315
316
317
318
319
# File 'lib/rack/request.rb', line 315

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

#bodyObject



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

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.



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

def content_charset
  media_type_params['charset']
end

#content_lengthObject



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

def content_length;  @env['CONTENT_LENGTH']                   end

#content_typeObject



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

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

#cookiesObject



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

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)


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

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.



260
261
262
263
264
# File 'lib/rack/request.rb', line 260

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)


172
173
174
175
176
# File 'lib/rack/request.rb', line 172

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



330
331
332
# File 'lib/rack/request.rb', line 330

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

#GETObject

Returns the data received in the query string.



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

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)


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

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)


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

def head?;    request_method == "HEAD"    end

#hostObject



104
105
106
107
# File 'lib/rack/request.rb', line 104

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

#host_with_portObject



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

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



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

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)


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

def link?;    request_method == "LINK"    end

#loggerObject



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

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



40
41
42
# File 'lib/rack/request.rb', line 40

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


49
50
51
52
53
54
# File 'lib/rack/request.rb', line 49

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)


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

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.



227
228
229
230
231
# File 'lib/rack/request.rb', line 227

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)


180
181
182
# File 'lib/rack/request.rb', line 180

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)


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

def patch?;   request_method == "PATCH"   end

#pathObject



326
327
328
# File 'lib/rack/request.rb', line 326

def path
  script_name + path_info
end

#path_infoObject



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

def path_info;       @env["PATH_INFO"].to_s                   end

#path_info=(s) ⇒ Object



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

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

#portObject



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

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.



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

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)


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

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)


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

def put?;     request_method == "PUT"     end

#query_stringObject



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

def query_string;    @env["QUERY_STRING"].to_s                end

#refererObject Also known as: referrer

the referer of the client



284
285
286
# File 'lib/rack/request.rb', line 284

def referer
  @env['HTTP_REFERER']
end

#request_methodObject



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

def request_method;  @env["REQUEST_METHOD"]                   end

#schemeObject



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

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



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

def script_name;     @env["SCRIPT_NAME"].to_s                 end

#script_name=(s) ⇒ Object



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

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

#sessionObject



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

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

#session_optionsObject



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

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

#ssl?Boolean

Returns:

  • (Boolean)


78
79
80
# File 'lib/rack/request.rb', line 78

def ssl?
  scheme == 'https'
end

#trace?Boolean

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

Returns:

  • (Boolean)


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

def trace?;   request_method == "TRACE"   end

#trusted_proxy?(ip) ⇒ Boolean

Returns:

  • (Boolean)


342
343
344
# File 'lib/rack/request.rb', line 342

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)


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

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.



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

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.



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

def url
  base_url + fullpath
end

#user_agentObject



289
290
291
# File 'lib/rack/request.rb', line 289

def user_agent
  @env['HTTP_USER_AGENT']
end

#values_at(*keys) ⇒ Object

like Hash#values_at



279
280
281
# File 'lib/rack/request.rb', line 279

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

#xhr?Boolean

Returns:

  • (Boolean)


311
312
313
# File 'lib/rack/request.rb', line 311

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