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

#accept_encodingObject



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

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

#accept_languageObject



611
612
613
# File 'lib/rack/request.rb', line 611

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



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

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.



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

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



603
604
605
# File 'lib/rack/request.rb', line 603

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
493
494
495
496
497
# File 'lib/rack/request.rb', line 484

def GET
  rr_query_string = get_header(RACK_REQUEST_QUERY_STRING)
  query_string = self.query_string
  if rr_query_string == query_string
    get_header(RACK_REQUEST_QUERY_HASH)
  else
    if rr_query_string
      warn "query string used for GET parsing different from current query string. Starting in Rack 3.2, Rack will used the cached GET value instead of parsing the current query string.", uplevel: 1
    end
    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.



556
557
558
# File 'lib/rack/request.rb', line 556

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



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

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.



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
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
# File 'lib/rack/request.rb', line 503

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

  begin
    rack_input = get_header(RACK_INPUT)

    # If the form hash was already memoized:
    if form_hash = get_header(RACK_REQUEST_FORM_HASH)
      form_input = get_header(RACK_REQUEST_FORM_INPUT)
      # And it was memoized from the same input:
      if form_input.equal?(rack_input)
        return form_hash
      elsif form_input
        warn "input stream used for POST parsing different from current input stream. Starting in Rack 3.2, Rack will used the cached POST value instead of parsing the current input stream.", uplevel: 1
      end
    end

    # Otherwise, figure out how to parse the input:
    if rack_input.nil?
      set_header RACK_REQUEST_FORM_INPUT, nil
      set_header(RACK_REQUEST_FORM_HASH, {})
    elsif form_data? || parseable_data?
      if pairs = Rack::Multipart.parse_multipart(env, Rack::Multipart::ParamList)
        set_header RACK_REQUEST_FORM_PAIRS, pairs
        set_header RACK_REQUEST_FORM_HASH, expand_param_pairs(pairs)
      else
        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)


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

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.



565
566
567
568
569
570
571
572
573
574
575
576
577
578
# File 'lib/rack/request.rb', line 565

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.



595
596
597
# File 'lib/rack/request.rb', line 595

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



620
621
622
623
624
# File 'lib/rack/request.rb', line 620

def values_at(*keys)
  warn("Request#values_at is deprecated and will be removed in a future version of Rack. Please use request.params.values_at instead", uplevel: 1)
  
  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