Module: Rack::Request::Helpers

Included in:
Rack::Request
Defined in:
lib/rack/request.rb

Constant Summary collapse

FORM_DATA_MEDIA_TYPES =

The set of form-data media-types. Requests that do not indicate one of the media types present 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 present 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 }
HTTP_X_FORWARDED_FOR =

The address of the client which connected to the proxy.

'HTTP_X_FORWARDED_FOR'
HTTP_X_FORWARDED_HOST =

The contents of the host/:authority header sent to the proxy.

'HTTP_X_FORWARDED_HOST'
HTTP_X_FORWARDED_SCHEME =

The value of the scheme sent to the proxy.

'HTTP_X_FORWARDED_SCHEME'
HTTP_X_FORWARDED_PROTO =

The protocol used to connect to the proxy.

'HTTP_X_FORWARDED_PROTO'
HTTP_X_FORWARDED_PORT =

The port used to connect to the proxy.

'HTTP_X_FORWARDED_PORT'
HTTP_X_FORWARDED_SSL =

Another way for specifing https scheme was used.

'HTTP_X_FORWARDED_SSL'

Instance Method Summary collapse

Instance Method Details

#[](key) ⇒ Object

shortcut for request.params



532
533
534
535
536
537
538
# File 'lib/rack/request.rb', line 532

def [](key)
  if $VERBOSE
    warn("Request#[] is deprecated and will be removed in a future version of Rack. Please use request.params[] instead")
  end

  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.



543
544
545
546
547
548
549
# File 'lib/rack/request.rb', line 543

def []=(key, value)
  if $VERBOSE
    warn("Request#[]= is deprecated and will be removed in a future version of Rack. Please use request.params[]= instead")
  end

  params[key.to_s] = value
end

#accept_encoding ⇒ Object



519
520
521
# File 'lib/rack/request.rb', line 519

def accept_encoding
  parse_http_accept_header(get_header("HTTP_ACCEPT_ENCODING"))
end

#accept_language ⇒ Object



523
524
525
# File 'lib/rack/request.rb', line 523

def accept_language
  parse_http_accept_header(get_header("HTTP_ACCEPT_LANGUAGE"))
end

#authority ⇒ Object

The authority of the incoming request as defined by RFC3976. https://tools.ietf.org/html/rfc3986#section-3.2

In HTTP/1, this is the host header. In HTTP/2, this is the :authority pseudo-header.



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

def authority
  forwarded_authority || host_authority || server_authority
end

#base_url ⇒ Object



502
503
504
# File 'lib/rack/request.rb', line 502

def base_url
  "#{scheme}://#{host_with_port}"
end

#body ⇒ Object



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

def body;            get_header(RACK_INPUT)                         end

#content_charset ⇒ Object

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.



400
401
402
# File 'lib/rack/request.rb', line 400

def content_charset
  media_type_params['charset']
end

#content_length ⇒ Object



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

def content_length;  get_header('CONTENT_LENGTH')                   end

#content_type ⇒ Object



271
272
273
274
# File 'lib/rack/request.rb', line 271

def content_type
  content_type = get_header('CONTENT_TYPE')
  content_type.nil? || content_type.empty? ? nil : content_type
end

#cookies ⇒ Object



256
257
258
259
260
261
262
263
264
265
266
267
268
269
# File 'lib/rack/request.rb', line 256

def cookies
  hash = fetch_header(RACK_REQUEST_COOKIE_HASH) do |key|
    set_header(key, {})
  end

  string = get_header(HTTP_COOKIE)

  unless string == get_header(RACK_REQUEST_COOKIE_STRING)
    hash.replace Utils.parse_cookies_header(string)
    set_header(RACK_REQUEST_COOKIE_STRING, string)
  end

  hash
end

#delete? ⇒ Boolean

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

Returns:

  • (Boolean)


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

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.



497
498
499
500
# File 'lib/rack/request.rb', line 497

def delete_param(k)
  post_value, get_value = self.POST.delete(k), self.GET.delete(k)
  post_value || get_value
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)


412
413
414
415
416
417
# File 'lib/rack/request.rb', line 412

def form_data?
  type = media_type
  meth = get_header(RACK_METHODOVERRIDE_ORIGINAL_METHOD) || get_header(REQUEST_METHOD)

  (meth == POST && type.nil?) || FORM_DATA_MEDIA_TYPES.include?(type)
end

#forwarded_authority ⇒ Object



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

def forwarded_authority
  if value = get_header(HTTP_X_FORWARDED_HOST)
    wrap_ipv6(split_header(value).first)
  end
end

#forwarded_for ⇒ Object



330
331
332
333
334
335
336
# File 'lib/rack/request.rb', line 330

def forwarded_for
  if value = get_header(HTTP_X_FORWARDED_FOR)
    split_header(value).map do |authority|
      split_authority(wrap_ipv6(authority))[1]
    end
  end
end

#forwarded_port ⇒ Object



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

def forwarded_port
  if value = get_header(HTTP_X_FORWARDED_PORT)
    split_header(value).map(&:to_i)
  end
end

#fullpath ⇒ Object



515
516
517
# File 'lib/rack/request.rb', line 515

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

#GET ⇒ Object

Returns the data received in the query string.



426
427
428
429
430
431
432
433
434
# File 'lib/rack/request.rb', line 426

def GET
  if get_header(RACK_REQUEST_QUERY_STRING) == query_string
    get_header(RACK_REQUEST_QUERY_HASH)
  else
    query_hash = parse_query(query_string, '&;')
    set_header(RACK_REQUEST_QUERY_STRING, query_string)
    set_header(RACK_REQUEST_QUERY_HASH, query_hash)
  end
end

#get? ⇒ Boolean

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

Returns:

  • (Boolean)


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

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)


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

def head?;    request_method == HEAD    end

#host ⇒ Object

Returns a formatted host, suitable for being used in a URI.



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

def host
  split_authority(self.authority)[0]
end

#host_authority ⇒ Object

The HTTP_HOST header.



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

def host_authority
  get_header(HTTP_HOST)
end

#host_with_port(authority = self.authority) ⇒ Object



285
286
287
288
289
290
291
292
293
# File 'lib/rack/request.rb', line 285

def host_with_port(authority = self.authority)
  host, _, port = split_authority(authority)

  if port == DEFAULT_PORTS[self.scheme]
    host
  else
    authority
  end
end

#hostname ⇒ Object

Returns an address suitable for being to resolve to an address. In the case of a domain name or IPv4 address, the result is the same as host. In the case of IPv6 or future address formats, the square brackets are removed.



304
305
306
# File 'lib/rack/request.rb', line 304

def hostname
  split_authority(self.authority)[1]
end

#ip ⇒ Object



354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
# File 'lib/rack/request.rb', line 354

def ip
  remote_addresses = split_header(get_header('REMOTE_ADDR'))
  external_addresses = reject_trusted_ip_addresses(remote_addresses)

  unless external_addresses.empty?
    return external_addresses.first
  end

  if forwarded_for = self.forwarded_for
    unless forwarded_for.empty?
      # The forwarded for addresses are ordered: client, proxy1, proxy2.
      # So we reject all the trusted addresses (proxy*) and return the
      # last client. Or if we trust everyone, we just return the first
      # address.
      return reject_trusted_ip_addresses(forwarded_for).last || forwarded_for.first
    end
  end

  # If all the addresses are trusted, and we aren't forwarded, just return
  # the first remote address, which represents the source of the request.
  remote_addresses.first
end

#link? ⇒ Boolean

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

Returns:

  • (Boolean)


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

def link?;    request_method == LINK    end

#logger ⇒ Object



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

def logger;          get_header(RACK_LOGGER)                        end

#media_type ⇒ Object

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: http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7



383
384
385
# File 'lib/rack/request.rb', line 383

def media_type
  MediaType.type(content_type)
end

#media_type_params ⇒ Object

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


392
393
394
# File 'lib/rack/request.rb', line 392

def media_type_params
  MediaType.params(content_type)
end

#multithread? ⇒ Boolean

Returns:

  • (Boolean)


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

def multithread?;    get_header(RACK_MULTITHREAD)                   end

#options? ⇒ Boolean

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

Returns:

  • (Boolean)


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

def options?; request_method == OPTIONS end

#params ⇒ Object

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.



468
469
470
# File 'lib/rack/request.rb', line 468

def params
  self.GET.merge(self.POST)
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)


421
422
423
# File 'lib/rack/request.rb', line 421

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)


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

def patch?;   request_method == PATCH   end

#path ⇒ Object



511
512
513
# File 'lib/rack/request.rb', line 511

def path
  script_name + path_info
end

#path_info ⇒ Object



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

def path_info;       get_header(PATH_INFO).to_s                     end

#path_info=(s) ⇒ Object



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

def path_info=(s);   set_header(PATH_INFO, s.to_s)                  end

#port ⇒ Object



308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/rack/request.rb', line 308

def port
  if authority = self.authority
    _, _, port = split_authority(self.authority)

    if port
      return port
    end
  end

  if forwarded_port = self.forwarded_port
    return forwarded_port.first
  end

  if scheme = self.scheme
    if port = DEFAULT_PORTS[self.scheme]
      return port
    end
  end

  self.server_port
end

#POST ⇒ Object

Returns the data received in the request body.

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



440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
# File 'lib/rack/request.rb', line 440

def POST
  if get_header(RACK_INPUT).nil?
    raise "Missing rack.input"
  elsif get_header(RACK_REQUEST_FORM_INPUT) == get_header(RACK_INPUT)
    get_header(RACK_REQUEST_FORM_HASH)
  elsif form_data? || parseable_data?
    unless set_header(RACK_REQUEST_FORM_HASH, parse_multipart)
      form_vars = get_header(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.end_with?("\0")

      set_header RACK_REQUEST_FORM_VARS, form_vars
      set_header RACK_REQUEST_FORM_HASH, parse_query(form_vars, '&')

      get_header(RACK_INPUT).rewind
    end
    set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
    get_header 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)


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

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)


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

def put?;     request_method == PUT     end

#query_string ⇒ Object



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

def query_string;    get_header(QUERY_STRING).to_s                  end

#referer ⇒ Object Also known as: referrer

the referer of the client



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

def referer;         get_header('HTTP_REFERER')                     end

#request_method ⇒ Object



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

def request_method;  get_header(REQUEST_METHOD)                     end

#scheme ⇒ Object



210
211
212
213
214
215
216
217
218
219
220
# File 'lib/rack/request.rb', line 210

def scheme
  if get_header(HTTPS) == 'on'
    'https'
  elsif get_header(HTTP_X_FORWARDED_SSL) == 'on'
    'https'
  elsif forwarded_scheme
    forwarded_scheme
  else
    get_header(RACK_URL_SCHEME)
  end
end

#script_name ⇒ Object



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

def script_name;     get_header(SCRIPT_NAME).to_s                   end

#script_name=(s) ⇒ Object



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

def script_name=(s); set_header(SCRIPT_NAME, s.to_s)                end

#server_authority ⇒ Object

The authority as defined by the SERVER_NAME and SERVER_PORT variables.



233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/rack/request.rb', line 233

def server_authority
  host = self.server_name
  port = self.server_port

  if host
    if port
      "#{host}:#{port}"
    else
      host
    end
  end
end

#server_name ⇒ Object



246
247
248
# File 'lib/rack/request.rb', line 246

def server_name
  get_header(SERVER_NAME)
end

#server_port ⇒ Object



250
251
252
253
254
# File 'lib/rack/request.rb', line 250

def server_port
  if port = get_header(SERVER_PORT)
    Integer(port)
  end
end

#session ⇒ Object



168
169
170
171
172
# File 'lib/rack/request.rb', line 168

def session
  fetch_header(RACK_SESSION) do |k|
    set_header RACK_SESSION, default_session
  end
end

#session_options ⇒ Object



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

def session_options
  fetch_header(RACK_SESSION_OPTIONS) do |k|
    set_header RACK_SESSION_OPTIONS, {}
  end
end

#ssl? ⇒ Boolean

Returns:

  • (Boolean)


350
351
352
# File 'lib/rack/request.rb', line 350

def ssl?
  scheme == 'https' || scheme == 'wss'
end

#trace? ⇒ Boolean

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

Returns:

  • (Boolean)


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

def trace?;   request_method == TRACE   end

#trusted_proxy?(ip) ⇒ Boolean

Returns:

  • (Boolean)


527
528
529
# File 'lib/rack/request.rb', line 527

def trusted_proxy?(ip)
  Rack::Request.ip_filter.call(ip)
end

#unlink? ⇒ Boolean

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

Returns:

  • (Boolean)


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

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.



477
478
479
480
481
482
483
484
485
486
487
488
489
490
# File 'lib/rack/request.rb', line 477

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
end

#url ⇒ Object

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



507
508
509
# File 'lib/rack/request.rb', line 507

def url
  base_url + fullpath
end

#user_agent ⇒ Object



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

def user_agent;      get_header('HTTP_USER_AGENT')                  end

#values_at(*keys) ⇒ Object

like Hash#values_at



552
553
554
# File 'lib/rack/request.rb', line 552

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

#xhr? ⇒ Boolean

Returns:

  • (Boolean)


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

def xhr?
  get_header("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest"
end