# module Rack::Request::Helpers

### Constants

AUTHORITY
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_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 specifing 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

### Public Instance Methods

GET() click to toggle source

Returns the data received in the query string.

    # 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

POST() click to toggle source

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

[](key) click to toggle source

shortcut for `request.params[key]`

    # File lib/rack/request.rb, line 535
    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) click to toggle source

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.

    # File lib/rack/request.rb, line 546
    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() click to toggle source

    # File lib/rack/request.rb, line 522
    def accept_encoding
      parse_http_accept_header(get_header("HTTP_ACCEPT_ENCODING"))
    end

accept_language() click to toggle source

    # File lib/rack/request.rb, line 526
    def accept_language
      parse_http_accept_header(get_header("HTTP_ACCEPT_LANGUAGE"))
    end

authority() click to toggle source

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 227
    def authority
      forwarded_authority || host_authority || server_authority
    end

base_url() click to toggle source

    # File lib/rack/request.rb, line 505
    def base_url
      "#{scheme}://#{host_with_port}"
    end

body() click to toggle source

    # File lib/rack/request.rb, line 150
    def body;            get_header(RACK_INPUT)                         end

content_charset() click to toggle source

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 400
    def content_charset
      media_type_params['charset']
    end

content_length() click to toggle source

    # File lib/rack/request.rb, line 159
    def content_length;  get_header('CONTENT_LENGTH')                   end

content_type() click to toggle source

    # 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() click to toggle source

    # 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?() click to toggle source

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

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

delete_param(k) click to toggle source

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

form_data?() click to toggle source

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 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() click to toggle source

    # 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() click to toggle source

    # 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() click to toggle source

    # 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() click to toggle source

    # File lib/rack/request.rb, line 518
    def fullpath
      query_string.empty? ? path : "#{path}?#{query_string}"
    end

get?() click to toggle source

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

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

head?() click to toggle source

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

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

host() click to toggle source

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

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

host_authority() click to toggle source

The `HTTP_HOST` header.

    # File lib/rack/request.rb, line 281
    def host_authority
      get_header(HTTP_HOST)
    end

host_with_port(authority = self.authority) click to toggle source

    # 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() click to toggle source

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 304
    def hostname
      split_authority(self.authority)[1]
    end

ip() click to toggle source

    # 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?() click to toggle source

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

    # File lib/rack/request.rb, line 193
    def link?;    request_method == LINK    end

logger() click to toggle source

    # File lib/rack/request.rb, line 160
    def logger;          get_header(RACK_LOGGER)                        end

media_type() click to toggle source

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

media_type_params() click to toggle source

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 392
    def media_type_params
      MediaType.params(content_type)
    end

multithread?() click to toggle source

    # File lib/rack/request.rb, line 162
    def multithread?;    get_header(RACK_MULTITHREAD)                   end

options?() click to toggle source

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

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

params() click to toggle source

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

parseable_data?() click to toggle source

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 421
    def parseable_data?
      PARSEABLE_DATA_MEDIA_TYPES.include?(media_type)
    end

patch?() click to toggle source

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

    # File lib/rack/request.rb, line 196
    def patch?;   request_method == PATCH   end

path() click to toggle source

    # File lib/rack/request.rb, line 514
    def path
      script_name + path_info
    end

path_info() click to toggle source

    # File lib/rack/request.rb, line 154
    def path_info;       get_header(PATH_INFO).to_s                     end

path_info=(s) click to toggle source

    # File lib/rack/request.rb, line 155
    def path_info=(s);   set_header(PATH_INFO, s.to_s)                  end

port() click to toggle source

    # 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?() click to toggle source

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

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

put?() click to toggle source

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

    # File lib/rack/request.rb, line 202
    def put?;     request_method == PUT     end

query_string() click to toggle source

    # File lib/rack/request.rb, line 158
    def query_string;    get_header(QUERY_STRING).to_s                  end

referer() click to toggle source

the referer of the client

    # File lib/rack/request.rb, line 165
    def referer;         get_header('HTTP_REFERER')                     end

Also aliased as: referrer
referrer()
Alias for: referer
request_method() click to toggle source

    # File lib/rack/request.rb, line 157
    def request_method;  get_header(REQUEST_METHOD)                     end

scheme() click to toggle source

    # 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() click to toggle source

    # File lib/rack/request.rb, line 151
    def script_name;     get_header(SCRIPT_NAME).to_s                   end

script_name=(s) click to toggle source

    # File lib/rack/request.rb, line 152
    def script_name=(s); set_header(SCRIPT_NAME, s.to_s)                end

server_authority() click to toggle source

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

    # 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() click to toggle source

    # File lib/rack/request.rb, line 246
    def server_name
      get_header(SERVER_NAME)
    end

server_port() click to toggle source

    # File lib/rack/request.rb, line 250
    def server_port
      if port = get_header(SERVER_PORT)
        Integer(port)
      end
    end

session() click to toggle source

    # 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() click to toggle source

    # 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?() click to toggle source

    # File lib/rack/request.rb, line 350
    def ssl?
      scheme == 'https' || scheme == 'wss'
    end

trace?() click to toggle source

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

    # File lib/rack/request.rb, line 205
    def trace?;   request_method == TRACE   end

trusted_proxy?(ip) click to toggle source

    # File lib/rack/request.rb, line 530
    def trusted_proxy?(ip)
      Rack::Request.ip_filter.call(ip)
    end

unlink?() click to toggle source

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

    # File lib/rack/request.rb, line 208
    def unlink?;  request_method == UNLINK  end

update_param(k, v) click to toggle source

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 480
    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() click to toggle source

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

    # File lib/rack/request.rb, line 510
    def url
      base_url + fullpath
    end

user_agent() click to toggle source

    # File lib/rack/request.rb, line 161
    def user_agent;      get_header('HTTP_USER_AGENT')                  end

values_at(*keys) click to toggle source

like Hash#values_at

    # File lib/rack/request.rb, line 555
    def values_at(*keys)
      keys.map { |key| params[key] }
    end

xhr?() click to toggle source

    # File lib/rack/request.rb, line 276
    def xhr?
      get_header("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest"
    end

### Private Instance Methods

allowed_scheme(header) click to toggle source

    # File lib/rack/request.rb, line 644
    def allowed_scheme(header)
      header if ALLOWED_SCHEMES.include?(header)
    end

default_session() click to toggle source

    # File lib/rack/request.rb, line 561
    def default_session; {}; end

extract_proto_header(header) click to toggle source

    # File lib/rack/request.rb, line 648
    def extract_proto_header(header)
      if header
        if (comma_index = header.index(','))
          header[0, comma_index]
        else
          header
        end
      end
    end

forwarded_scheme() click to toggle source

    # File lib/rack/request.rb, line 639
    def forwarded_scheme
      allowed_scheme(get_header(HTTP_X_FORWARDED_SCHEME)) ||
      allowed_scheme(extract_proto_header(get_header(HTTP_X_FORWARDED_PROTO)))
    end

parse_http_accept_header(header) click to toggle source

    # File lib/rack/request.rb, line 577
    def parse_http_accept_header(header)
      header.to_s.split(",").each(&:strip!).map do |part|
        attribute, parameters = part.split(";", 2).each(&:strip!)
        quality = 1.0
        if parameters and /\Aq=([\d.]+)/ =~ parameters
          quality = $1.to_f
        end
        [attribute, quality]
      end
    end

parse_multipart() click to toggle source

    # File lib/rack/request.rb, line 596
    def parse_multipart
      Rack::Multipart.extract_multipart(self, query_parser)
    end

parse_query(qs, d = '&') click to toggle source

    # File lib/rack/request.rb, line 592
    def parse_query(qs, d = '&')
      query_parser.parse_nested_query(qs, d)
    end

query_parser() click to toggle source

    # File lib/rack/request.rb, line 588
    def query_parser
      Utils.default_query_parser
    end

reject_trusted_ip_addresses(ip_addresses) click to toggle source

    # File lib/rack/request.rb, line 635
    def reject_trusted_ip_addresses(ip_addresses)
      ip_addresses.reject { |ip| trusted_proxy?(ip) }
    end

split_authority(authority) click to toggle source

    # File lib/rack/request.rb, line 622
    def split_authority(authority)
      if match = AUTHORITY.match(authority)
        if address = match[:ip6]
          return match[:host], address, match[:port]&.to_i
        else
          return match[:host], match[:host], match[:port]&.to_i
        end
      end

      # Give up!
      return authority, authority, nil
    end

split_header(value) click to toggle source

    # File lib/rack/request.rb, line 600
    def split_header(value)
      value ? value.strip.split(/[,\s]+/) : []
    end

wrap_ipv6(host) click to toggle source

Assist with compatibility when processing `X-Forwarded-For`.

    # File lib/rack/request.rb, line 564
    def wrap_ipv6(host)
      # Even thought IPv6 addresses should be wrapped in square brackets,
      # sometimes this is not done in various legacy/underspecified headers.
      # So we try to fix this situation for compatibility reasons.

      # Try to detect IPv6 addresses which aren't escaped yet:
      if !host.start_with?('[') && host.count(':') > 1
        "[#{host}]"
      else
        host
      end
    end