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"]
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
- SCHEME_WHITELIST
Attributes
The environment of the request.
Public Class Methods
# File lib/rack/request.rb, line 18 def initialize(env) @env = env end
Public Instance Methods
Returns the data received in the query string.
# File lib/rack/request.rb, line 187 def GET if @env["rack.request.query_string"] == query_string @env["rack.request.query_hash"] else p = parse_query({ :query => query_string, :separator => '&;' }) @env["rack.request.query_string"] = query_string @env["rack.request.query_hash"] = p 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 201 def POST if @env["rack.input"].nil? raise "Missing rack.input" elsif @env["rack.request.form_input"].equal? @env["rack.input"] @env["rack.request.form_hash"] elsif form_data? || parseable_data? 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({ :query => form_vars, :separator => '&' }) @env["rack.input"].rewind end @env["rack.request.form_input"] = @env["rack.input"] @env["rack.request.form_hash"] else {} end end
shortcut for request.params
# File lib/rack/request.rb, line 269 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 276 def []=(key, value) params[key.to_s] = value end
# File lib/rack/request.rb, line 336 def accept_encoding parse_http_accept_header(@env["HTTP_ACCEPT_ENCODING"]) end
# File lib/rack/request.rb, line 340 def accept_language parse_http_accept_header(@env["HTTP_ACCEPT_LANGUAGE"]) end
# File lib/rack/request.rb, line 317 def base_url url = "#{scheme}://#{host}" url << ":#{port}" if port != DEFAULT_PORTS[scheme] url end
# File lib/rack/request.rb, line 22 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 64 def content_charset media_type_params['charset'] end
# File lib/rack/request.rb, line 27 def content_length; @env['CONTENT_LENGTH'] end
# File lib/rack/request.rb, line 29 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 116 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 262 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 174 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 332 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 119 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 122 def head?; request_method == HEAD end
# File lib/rack/request.rb, line 106 def host # Remove port number. host_with_port.to_s.sub(/:\d+\z/, '') end
# File lib/rack/request.rb, line 84 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 348 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']) return reject_trusted_ip_addresses(forwarded_ips).last || @env["REMOTE_ADDR"] end
Checks the HTTP request method (or verb) to see if it was of type LINK
# File lib/rack/request.rb, line 128 def link?; request_method == "LINK" end
# File lib/rack/request.rb, line 36 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 44 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 53 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, strip_doublequotes(v)] }.flatten] end
Checks the HTTP request method (or verb) to see if it was of type OPTIONS
# File lib/rack/request.rb, line 125 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 229 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 182 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 131 def patch?; request_method == "PATCH" end
# File lib/rack/request.rb, line 328 def path script_name + path_info end
# File lib/rack/request.rb, line 24 def path_info; @env[PATH_INFO].to_s end
# File lib/rack/request.rb, line 112 def path_info=(s); @env["PATH_INFO"] = s.to_s end
# File lib/rack/request.rb, line 92 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] elsif @env.has_key?("HTTP_X_FORWARDED_PROTO") DEFAULT_PORTS[@env['HTTP_X_FORWARDED_PROTO'].split(',')[0]] 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 134 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 137 def put?; request_method == "PUT" end
# File lib/rack/request.rb, line 26 def query_string; @env[QUERY_STRING].to_s end
the referer of the client
# File lib/rack/request.rb, line 286 def referer @env['HTTP_REFERER'] end
# File lib/rack/request.rb, line 25 def request_method; @env["REQUEST_METHOD"] end
# File lib/rack/request.rb, line 68 def scheme if @env['HTTPS'] == 'on' 'https' elsif @env['HTTP_X_FORWARDED_SSL'] == 'on' 'https' elsif forwarded_scheme forwarded_scheme else @env["rack.url_scheme"] end end
# File lib/rack/request.rb, line 23 def script_name; @env[SCRIPT_NAME].to_s end
# File lib/rack/request.rb, line 111 def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end
# File lib/rack/request.rb, line 34 def session; @env['rack.session'] ||= {} end
# File lib/rack/request.rb, line 35 def session_options; @env['rack.session.options'] ||= {} end
# File lib/rack/request.rb, line 80 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 140 def trace?; request_method == "TRACE" end
# File lib/rack/request.rb, line 344 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
Checks the HTTP request method (or verb) to see if it was of type UNLINK
# File lib/rack/request.rb, line 143 def unlink?; request_method == "UNLINK" 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 240 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 324 def url base_url + fullpath end
# File lib/rack/request.rb, line 291 def user_agent @env['HTTP_USER_AGENT'] end
like Hash#values_at
# File lib/rack/request.rb, line 281 def values_at(*keys) keys.map{|key| params[key] } end
# File lib/rack/request.rb, line 313 def xhr? @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest" end
Protected Instance Methods
# File lib/rack/request.rb, line 378 def parse_http_accept_header(header) header.to_s.split(/\s*,\s*/).map do |part| attribute, parameters = part.split(/\s*;\s*/, 2) quality = 1.0 if parameters and /\Aq=([\d.]+)/ =~ parameters quality = $1.to_f end [attribute, quality] end end
# File lib/rack/request.rb, line 374 def parse_multipart(env) Rack::Multipart.parse_multipart(env) end
# File lib/rack/request.rb, line 368 def parse_query(qs) d = '&' qs, d = qs[:query], qs[:separator] if Hash === qs Utils.parse_nested_query(qs, d) end
# File lib/rack/request.rb, line 364 def reject_trusted_ip_addresses(ip_addresses) ip_addresses.reject { |ip| trusted_proxy?(ip) } end
# File lib/rack/request.rb, line 360 def split_ip_addresses(ip_addresses) ip_addresses ? ip_addresses.strip.split(/[,\s]+/) : [] end
Private Instance Methods
# File lib/rack/request.rb, line 398 def forwarded_scheme scheme_headers = [ @env['HTTP_X_FORWARDED_SCHEME'], @env['HTTP_X_FORWARDED_PROTO'].to_s.split(',')[0] ] scheme_headers.each do |header| return header if SCHEME_WHITELIST.include?(header) end nil end
# File lib/rack/request.rb, line 390 def strip_doublequotes(s) if s[0] == ?" && s[-1] == ?" s[1..-2] else s end end