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_FORWARDED =
'HTTP_FORWARDED'
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 specifying https scheme was used.

'HTTP_X_FORWARDED_SSL'

Instance Method Summary collapse

Instance Method Details

#[](key) ⇒ Object

shortcut for request.params[key]


598
599
600
601
602
# File 'lib/rack/request.rb', line 598

def [](key)
  warn("Request#[] is deprecated and will be removed in a future version of Rack. Please use request.params[] instead", uplevel: 1)

  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.


607
608
609
610
611
# File 'lib/rack/request.rb', line 607

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

  params[key.to_s] = value
end

#accept_encodingObject


585
586
587
# File 'lib/rack/request.rb', line 585

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

#accept_languageObject


589
590
591
# File 'lib/rack/request.rb', line 589

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

#authorityObject

The authority of the incoming request as defined by RFC3976. 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.


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

def authority
  forwarded_authority || host_authority || server_authority
end

#base_urlObject


568
569
570
# File 'lib/rack/request.rb', line 568

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

#bodyObject


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

def body;            get_header(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.


458
459
460
# File 'lib/rack/request.rb', line 458

def content_charset
  media_type_params['charset']
end

#content_lengthObject


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

def content_length;  get_header('CONTENT_LENGTH')                   end

#content_typeObject


308
309
310
311
# File 'lib/rack/request.rb', line 308

def content_type
  content_type = get_header('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
# File 'lib/rack/request.rb', line 293

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)

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

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['rack.input'] is not touched.


563
564
565
566
# File 'lib/rack/request.rb', line 563

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)

470
471
472
473
474
475
# File 'lib/rack/request.rb', line 470

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_authorityObject


393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
# File 'lib/rack/request.rb', line 393

def forwarded_authority
  forwarded_priority.each do |type|
    case type
    when :forwarded
      if forwarded = get_http_forwarded(:host)
        return forwarded.last
      end
    when :x_forwarded
      if value = get_header(HTTP_X_FORWARDED_HOST)
        return wrap_ipv6(split_header(value).last)
      end
    end
  end

  nil
end

#forwarded_forObject


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

def forwarded_for
  forwarded_priority.each do |type|
    case type
    when :forwarded
      if forwarded_for = get_http_forwarded(:for)
        return(forwarded_for.map! do |authority|
          split_authority(authority)[1]
        end)
      end
    when :x_forwarded
      if value = get_header(HTTP_X_FORWARDED_FOR)
        return(split_header(value).map do |authority|
          split_authority(wrap_ipv6(authority))[1]
        end)
      end
    end
  end

  nil
end

#forwarded_portObject


374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# File 'lib/rack/request.rb', line 374

def forwarded_port
  forwarded_priority.each do |type|
    case type
    when :forwarded
      if forwarded = get_http_forwarded(:for)
        return(forwarded.map do |authority|
          split_authority(authority)[2]
        end.compact)
      end
    when :x_forwarded
      if value = get_header(HTTP_X_FORWARDED_PORT)
        return split_header(value).map(&:to_i)
      end
    end
  end

  nil
end

#fullpathObject


581
582
583
# File 'lib/rack/request.rb', line 581

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

#GETObject

Returns the data received in the query string.


484
485
486
487
488
489
490
491
492
# File 'lib/rack/request.rb', line 484

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)

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

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)

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

def head?;    request_method == HEAD    end

#hostObject

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


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

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

#host_authorityObject

The `HTTP_HOST` header.


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

def host_authority
  get_header(HTTP_HOST)
end

#host_with_port(authority = self.authority) ⇒ Object


322
323
324
325
326
327
328
329
330
# File 'lib/rack/request.rb', line 322

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

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

#hostnameObject

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.


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

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

#ipObject


414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
# File 'lib/rack/request.rb', line 414

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.last
  end

  if (forwarded_for = self.forwarded_for) && !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

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

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

def link?;    request_method == LINK    end

#loggerObject


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

def logger;          get_header(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


441
442
443
# File 'lib/rack/request.rb', line 441

def media_type
  MediaType.type(content_type)
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' }

450
451
452
# File 'lib/rack/request.rb', line 450

def media_type_params
  MediaType.params(content_type)
end

#options?Boolean

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

Returns:

  • (Boolean)

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

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.


534
535
536
# File 'lib/rack/request.rb', line 534

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)

479
480
481
# File 'lib/rack/request.rb', line 479

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)

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

def patch?;   request_method == PATCH   end

#pathObject


577
578
579
# File 'lib/rack/request.rb', line 577

def path
  script_name + path_info
end

#path_infoObject


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

def path_info;       get_header(PATH_INFO).to_s                     end

#path_info=(s) ⇒ Object


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

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

#portObject


345
346
347
348
349
350
351
# File 'lib/rack/request.rb', line 345

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

  port || forwarded_port&.last || DEFAULT_PORTS[scheme] || server_port
end

#POSTObject

Returns the data received in the request body.

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


498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
# File 'lib/rack/request.rb', line 498

def POST
  if error = get_header(RACK_REQUEST_FORM_ERROR)
    raise error.class, error.message, cause: error.cause
  end

  begin
    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, '&')
      end
      set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
      get_header RACK_REQUEST_FORM_HASH
    else
      set_header RACK_REQUEST_FORM_INPUT, get_header(RACK_INPUT)
      set_header(RACK_REQUEST_FORM_HASH, {})
    end
  rescue => error
    set_header(RACK_REQUEST_FORM_ERROR, error)
    raise
  end
end

#post?Boolean

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

Returns:

  • (Boolean)

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

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)

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

def put?;     request_method == PUT     end

#query_stringObject


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

def query_string;    get_header(QUERY_STRING).to_s                  end

#refererObject Also known as: referrer

the referer of the client


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

def referer;         get_header('HTTP_REFERER')                     end

#request_methodObject


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

def request_method;  get_header(REQUEST_METHOD)                     end

#schemeObject


249
250
251
252
253
254
255
256
257
258
259
# File 'lib/rack/request.rb', line 249

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_nameObject


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

def script_name;     get_header(SCRIPT_NAME).to_s                   end

#script_name=(s) ⇒ Object


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

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

#server_authorityObject

The authority as defined by the `SERVER_NAME` and `SERVER_PORT` variables.


272
273
274
275
276
277
278
279
280
281
282
283
# File 'lib/rack/request.rb', line 272

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

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

#server_nameObject


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

def server_name
  get_header(SERVER_NAME)
end

#server_portObject


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

def server_port
  get_header(SERVER_PORT)
end

#sessionObject


207
208
209
210
211
# File 'lib/rack/request.rb', line 207

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

#session_optionsObject


213
214
215
216
217
# File 'lib/rack/request.rb', line 213

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

#ssl?Boolean

Returns:

  • (Boolean)

410
411
412
# File 'lib/rack/request.rb', line 410

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)

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

def trace?;   request_method == TRACE   end

#trusted_proxy?(ip) ⇒ Boolean

Returns:

  • (Boolean)

593
594
595
# File 'lib/rack/request.rb', line 593

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)

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

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['rack.input'] is not touched.


543
544
545
546
547
548
549
550
551
552
553
554
555
556
# File 'lib/rack/request.rb', line 543

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

#urlObject

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


573
574
575
# File 'lib/rack/request.rb', line 573

def url
  base_url + fullpath
end

#user_agentObject


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

def user_agent;      get_header('HTTP_USER_AGENT')                  end

#values_at(*keys) ⇒ Object

like Hash#values_at


614
615
616
# File 'lib/rack/request.rb', line 614

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?
  get_header("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest"
end