class Rack::Request
Rack::Request provides a convenient interface to
a Rack environment. It is stateless, the
environment env
passed to the constructor will be directly
modified.
req = Rack::Request.new(env) req.post? req.params["data"]
The environment hash passed will store a reference to the Request object instantiated so that it will only instantiate if an instance of the Request object doesn't already exist.
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 presents in this list will not be eligible for form-data / param parsing.
- PARSEABLE_DATA_MEDIA_TYPES
The set of media-types. Requests that do not indicate one of the media types presents in this list will not be eligible for param parsing like soap attachments or generic multiparts
Attributes
The environment of the request.
Public Class Methods
# File lib/rack/request.rb, line 20 def initialize(env) @env = env end
Public Instance Methods
Returns the data received in the query string.
# File lib/rack/request.rb, line 183 def GET if @env["rack.request.query_string"] == query_string @env["rack.request.query_hash"] else @env["rack.request.query_string"] = query_string @env["rack.request.query_hash"] = parse_query(query_string) end 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 196 def POST if @env["rack.input"].nil? raise "Missing rack.input" elsif @env["rack.request.form_input"].eql? @env["rack.input"] @env["rack.request.form_hash"] elsif form_data? || parseable_data? @env["rack.request.form_input"] = @env["rack.input"] unless @env["rack.request.form_hash"] = parse_multipart(env) form_vars = @env["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[-1] == ?\0 @env["rack.request.form_vars"] = form_vars @env["rack.request.form_hash"] = parse_query(form_vars) @env["rack.input"].rewind end @env["rack.request.form_hash"] else {} end end
shortcut for request.params
# File lib/rack/request.rb, line 264 def [](key) params[key.to_s] end
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.
# File lib/rack/request.rb, line 271 def []=(key, value) params[key.to_s] = value end
# File lib/rack/request.rb, line 331 def accept_encoding @env["HTTP_ACCEPT_ENCODING"].to_s.split(/\s*,\s*/).map do |part| encoding, parameters = part.split(/\s*;\s*/, 2) quality = 1.0 if parameters and /\Aq=([\d.]+)/ =~ parameters quality = $1.to_f end [encoding, quality] end end
# File lib/rack/request.rb, line 312 def base_url url = "#{scheme}://#{host}" url << ":#{port}" if port != DEFAULT_PORTS[scheme] url end
# File lib/rack/request.rb, line 24 def body; @env["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 66 def content_charset media_type_params['charset'] end
# File lib/rack/request.rb, line 29 def content_length; @env['CONTENT_LENGTH'] end
# File lib/rack/request.rb, line 31 def content_type content_type = @env['CONTENT_TYPE'] content_type.nil? || content_type.empty? ? nil : content_type end
Checks the HTTP request method (or verb) to see if it was of type DELETE
# File lib/rack/request.rb, line 118 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 is not touched.
# File lib/rack/request.rb, line 257 def delete_param(k) v = [ self.POST.delete(k), self.GET.delete(k) ].compact.first @params = nil v 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 170 def form_data? type = media_type meth = env["rack.methodoverride.original_method"] || env['REQUEST_METHOD'] (meth == 'POST' && type.nil?) || FORM_DATA_MEDIA_TYPES.include?(type) end
# File lib/rack/request.rb, line 327 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 121 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 124 def head?; request_method == "HEAD" end
# File lib/rack/request.rb, line 108 def host # Remove port number. host_with_port.to_s.gsub(/:\d+\z/, '') end
# File lib/rack/request.rb, line 88 def host_with_port if forwarded = @env["HTTP_X_FORWARDED_HOST"] forwarded.split(/,\s?/).last else @env['HTTP_HOST'] || "#{@env['SERVER_NAME'] || @env['SERVER_ADDR']}:#{@env['SERVER_PORT']}" end end
# File lib/rack/request.rb, line 346 def ip remote_addrs = split_ip_addresses(@env['REMOTE_ADDR']) remote_addrs = reject_trusted_ip_addresses(remote_addrs) return remote_addrs.first if remote_addrs.any? forwarded_ips = split_ip_addresses(@env['HTTP_X_FORWARDED_FOR']) if client_ip = @env['HTTP_CLIENT_IP'] # If forwarded_ips doesn't include the client_ip, it might be an # ip spoofing attempt, so we ignore HTTP_CLIENT_IP return client_ip if forwarded_ips.include?(client_ip) end return reject_trusted_ip_addresses(forwarded_ips).last || @env["REMOTE_ADDR"] end
# File lib/rack/request.rb, line 38 def logger; @env['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 46 def media_type content_type && content_type.split(/\s*[;,]\s*/, 2).first.downcase 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 55 def media_type_params return {} if content_type.nil? Hash[*content_type.split(/\s*[;,]\s*/)[1..-1]. collect { |s| s.split('=', 2) }. map { |k,v| [k.downcase, v] }.flatten] end
Checks the HTTP request method (or verb) to see if it was of type OPTIONS
# File lib/rack/request.rb, line 127 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 224 def params @params ||= self.GET.merge(self.POST) rescue EOFError self.GET.dup 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 178 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 130 def patch?; request_method == "PATCH" end
# File lib/rack/request.rb, line 323 def path script_name + path_info end
# File lib/rack/request.rb, line 26 def path_info; @env["PATH_INFO"].to_s end
# File lib/rack/request.rb, line 114 def path_info=(s); @env["PATH_INFO"] = s.to_s end
# File lib/rack/request.rb, line 96 def port if port = host_with_port.split(/:/)[1] port.to_i elsif port = @env['HTTP_X_FORWARDED_PORT'] port.to_i elsif @env.has_key?("HTTP_X_FORWARDED_HOST") DEFAULT_PORTS[scheme] else @env["SERVER_PORT"].to_i end end
Checks the HTTP request method (or verb) to see if it was of type #POST
# File lib/rack/request.rb, line 133 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 136 def put?; request_method == "PUT" end
# File lib/rack/request.rb, line 28 def query_string; @env["QUERY_STRING"].to_s end
the referer of the client
# File lib/rack/request.rb, line 281 def referer @env['HTTP_REFERER'] end
# File lib/rack/request.rb, line 27 def request_method; @env["REQUEST_METHOD"] end
# File lib/rack/request.rb, line 70 def scheme if @env['HTTPS'] == 'on' 'https' elsif @env['HTTP_X_FORWARDED_SSL'] == 'on' 'https' elsif @env['HTTP_X_FORWARDED_SCHEME'] @env['HTTP_X_FORWARDED_SCHEME'] elsif @env['HTTP_X_FORWARDED_PROTO'] @env['HTTP_X_FORWARDED_PROTO'].split(',')[0] else @env["rack.url_scheme"] end end
# File lib/rack/request.rb, line 25 def script_name; @env["SCRIPT_NAME"].to_s end
# File lib/rack/request.rb, line 113 def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end
# File lib/rack/request.rb, line 36 def session; @env['rack.session'] ||= {} end
# File lib/rack/request.rb, line 37 def session_options; @env['rack.session.options'] ||= {} end
# File lib/rack/request.rb, line 84 def ssl? scheme == 'https' end
Checks the HTTP request method (or verb) to see if it was of type TRACE
# File lib/rack/request.rb, line 139 def trace?; request_method == "TRACE" end
# File lib/rack/request.rb, line 342 def trusted_proxy?(ip) ip =~ /\A127\.0\.0\.1\Z|\A(10|172\.(1[6-9]|2[0-9]|30|31)|192\.168)\.|\A::1\Z|\Afd[0-9a-f]{2}:.+|\Alocalhost\Z|\Aunix\Z|\Aunix:/i 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 is not touched.
# File lib/rack/request.rb, line 235 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 @params = nil nil end
Tries to return a remake of the original request URL as a string.
# File lib/rack/request.rb, line 319 def url base_url + fullpath end
# File lib/rack/request.rb, line 286 def user_agent @env['HTTP_USER_AGENT'] end
like Hash#values_at
# File lib/rack/request.rb, line 276 def values_at(*keys) keys.map{|key| params[key] } end
# File lib/rack/request.rb, line 308 def xhr? @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" end
Protected Instance Methods
# File lib/rack/request.rb, line 376 def parse_multipart(env) Rack::Multipart.parse_multipart(env) end
# File lib/rack/request.rb, line 372 def parse_query(qs) Utils.parse_nested_query(qs) end
# File lib/rack/request.rb, line 368 def reject_trusted_ip_addresses(ip_addresses) ip_addresses.reject { |ip| trusted_proxy?(ip) } end
# File lib/rack/request.rb, line 364 def split_ip_addresses(ip_addresses) ip_addresses ? ip_addresses.strip.split(/[,\s]+/) : [] end