module Rack::Request::Helpers

Constants

DEFAULT_PORTS

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

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.

HTTP_FORWARDED
HTTP_X_FORWARDED_FOR

The address of the client which connected to the proxy.

HTTP_X_FORWARDED_HOST

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

HTTP_X_FORWARDED_PORT

The port used to connect to the proxy.

HTTP_X_FORWARDED_PROTO

The protocol used to connect to the proxy.

HTTP_X_FORWARDED_SCHEME

The value of the scheme sent to the proxy.

HTTP_X_FORWARDED_SSL

Another way for specifying https scheme was used.

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

Attributes

Allow overriding the query parser that the receiver will use. By default Rack::Utils.default_query_parser is used.

Public Instance Methods

Returns the data received in the query string.

# File lib/rack/request.rb, line 491
def GET
  get_header(RACK_REQUEST_QUERY_HASH) || set_header(RACK_REQUEST_QUERY_HASH, parse_query(query_string, '&'))
end

Returns the data received in the request body.

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

# File lib/rack/request.rb, line 542
def POST
  if form_hash = get_header(RACK_REQUEST_FORM_HASH)
    return form_hash
  elsif error = get_header(RACK_REQUEST_FORM_ERROR)
    raise error.class, error.message, cause: error.cause
  end

  pairs = form_pairs
  set_header RACK_REQUEST_FORM_HASH, expand_param_pairs(pairs)
end
# File lib/rack/request.rb, line 611
def accept_encoding
  parse_http_accept_header(get_header("HTTP_ACCEPT_ENCODING"))
end
# File lib/rack/request.rb, line 615
def accept_language
  parse_http_accept_header(get_header("HTTP_ACCEPT_LANGUAGE"))
end

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.

# File lib/rack/request.rb, line 271
def authority
  forwarded_authority || host_authority || server_authority
end
# File lib/rack/request.rb, line 594
def base_url
  "#{scheme}://#{host_with_port}"
end
# File lib/rack/request.rb, line 195
def body;            get_header(RACK_INPUT)                         end

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.

# File lib/rack/request.rb, line 465
def content_charset
  media_type_params['charset']
end
# File lib/rack/request.rb, line 204
def content_length;  get_header('CONTENT_LENGTH')                   end
# File lib/rack/request.rb, line 313
def content_type
  content_type = get_header('CONTENT_TYPE')
  content_type.nil? || content_type.empty? ? nil : content_type
end
# File lib/rack/request.rb, line 298
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

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

# File lib/rack/request.rb, line 225
def delete?;  request_method == DELETE  end

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.

# File lib/rack/request.rb, line 589
def delete_param(k)
  post_value, get_value = self.POST.delete(k), self.GET.delete(k)
  post_value || get_value
end

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.

# File lib/rack/request.rb, line 477
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

Returns the form data pairs received in the request body.

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

# File lib/rack/request.rb, line 499
def form_pairs
  if pairs = get_header(RACK_REQUEST_FORM_PAIRS)
    return pairs
  elsif error = get_header(RACK_REQUEST_FORM_ERROR)
    raise error.class, error.message, cause: error.cause
  end

  begin
    rack_input = get_header(RACK_INPUT)

    # Otherwise, figure out how to parse the input:
    if rack_input.nil?
      set_header(RACK_REQUEST_FORM_PAIRS, [])
    elsif form_data? || parseable_data?
      if pairs = Rack::Multipart.parse_multipart(env, Rack::Multipart::ParamList)
        set_header RACK_REQUEST_FORM_PAIRS, pairs
      else
        # Add 2 bytes. One to check whether it is over the limit, and a second
        # in case the slice! call below removes the last byte
        # If read returns nil, use the empty string
        form_vars = get_header(RACK_INPUT).read(query_parser.bytesize_limit + 2) || ''

        # 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
        pairs = query_parser.parse_query_pairs(form_vars, '&')
        set_header(RACK_REQUEST_FORM_PAIRS, pairs)
      end
    else
      set_header(RACK_REQUEST_FORM_PAIRS, [])
    end
  rescue => error
    set_header(RACK_REQUEST_FORM_ERROR, error)
    raise
  end
end
# File lib/rack/request.rb, line 398
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)) && (x_forwarded_host = split_header(value).last)
        return wrap_ipv6(x_forwarded_host)
      end
    end
  end

  nil
end
# File lib/rack/request.rb, line 358
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
# File lib/rack/request.rb, line 379
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
# File lib/rack/request.rb, line 607
def fullpath
  query_string.empty? ? path : "#{path}?#{query_string}"
end

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

# File lib/rack/request.rb, line 228
def get?;     request_method == GET     end

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

# File lib/rack/request.rb, line 231
def head?;    request_method == HEAD    end

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

# File lib/rack/request.rb, line 338
def host
  split_authority(self.authority)[0]
end

The ‘HTTP_HOST` header.

# File lib/rack/request.rb, line 323
def host_authority
  get_header(HTTP_HOST)
end
# File lib/rack/request.rb, line 327
def host_with_port(authority = self.authority)
  host, _, port = split_authority(authority)

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

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.

# File lib/rack/request.rb, line 346
def hostname
  split_authority(self.authority)[1]
end
# File lib/rack/request.rb, line 419
def ip
  remote_addresses = split_header(get_header('REMOTE_ADDR'))

  remote_addresses.reverse_each do |ip|
    return ip unless trusted_proxy?(ip)
  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.
    forwarded_for.reverse_each do |ip|
      return ip unless trusted_proxy?(ip)
    end
    return 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
# File lib/rack/request.rb, line 205
def logger;          get_header(RACK_LOGGER)                        end

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

# File lib/rack/request.rb, line 448
def media_type
  MediaType.type(content_type)
end

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' }
# File lib/rack/request.rb, line 457
def media_type_params
  MediaType.params(content_type)
end

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

# File lib/rack/request.rb, line 234
def options?; request_method == OPTIONS end

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.

# File lib/rack/request.rb, line 556
def params
  self.GET.merge(self.POST)
end

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

# File lib/rack/request.rb, line 486
def parseable_data?
  PARSEABLE_DATA_MEDIA_TYPES.include?(media_type)
end

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

# File lib/rack/request.rb, line 240
def patch?;   request_method == PATCH   end
# File lib/rack/request.rb, line 603
def path
  script_name + path_info
end
# File lib/rack/request.rb, line 199
def path_info;       get_header(PATH_INFO).to_s                     end
# File lib/rack/request.rb, line 200
def path_info=(s);   set_header(PATH_INFO, s.to_s)                  end
# File lib/rack/request.rb, line 350
def port
  if authority = self.authority
    _, _, port = split_authority(authority)
  end

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

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

# File lib/rack/request.rb, line 243
def post?;    request_method == POST    end

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

# File lib/rack/request.rb, line 246
def put?;     request_method == PUT     end
# File lib/rack/request.rb, line 203
def query_string;    get_header(QUERY_STRING).to_s                  end

the referer of the client

# File lib/rack/request.rb, line 209
def referer;         get_header('HTTP_REFERER')                     end
Also aliased as: referrer
# File lib/rack/request.rb, line 202
def request_method;  get_header(REQUEST_METHOD)                     end
# File lib/rack/request.rb, line 254
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
# File lib/rack/request.rb, line 196
def script_name;     get_header(SCRIPT_NAME).to_s                   end
# File lib/rack/request.rb, line 197
def script_name=(s); set_header(SCRIPT_NAME, s.to_s)                end

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

# File lib/rack/request.rb, line 277
def server_authority
  host = self.server_name
  port = self.server_port

  if host
    if port
      "#{host}:#{port}"
    else
      host
    end
  end
end
# File lib/rack/request.rb, line 290
def server_name
  get_header(SERVER_NAME)
end
# File lib/rack/request.rb, line 294
def server_port
  get_header(SERVER_PORT)
end
# File lib/rack/request.rb, line 212
def session
  fetch_header(RACK_SESSION) do |k|
    set_header RACK_SESSION, default_session
  end
end
# File lib/rack/request.rb, line 218
def session_options
  fetch_header(RACK_SESSION_OPTIONS) do |k|
    set_header RACK_SESSION_OPTIONS, {}
  end
end
# File lib/rack/request.rb, line 415
def ssl?
  scheme == 'https' || scheme == 'wss'
end

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

# File lib/rack/request.rb, line 249
def trace?;   request_method == TRACE   end
# File lib/rack/request.rb, line 619
def trusted_proxy?(ip)
  Rack::Request.ip_filter.call(ip)
end

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.

# File lib/rack/request.rb, line 569
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

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

# File lib/rack/request.rb, line 599
def url
  base_url + fullpath
end
# File lib/rack/request.rb, line 206
def user_agent;      get_header('HTTP_USER_AGENT')                  end
# File lib/rack/request.rb, line 318
def xhr?
  get_header("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest"
end