Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 247 lines (209 sloc) 8.116 kb
7ed819a Christian Neukirchen Add Rack::Response and Rack::Utils
chneukirchen authored
1 require 'rack/utils'
2
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
3 module Rack
376fa1e Christian Neukirchen Add RDocs
chneukirchen authored
4 # Rack::Request provides a convenient interface to a Rack
5 # environment. It is stateless, the environment +env+ passed to the
6 # constructor will be directly modified.
7 #
8 # req = Rack::Request.new(env)
9 # req.post?
10 # req.params["data"]
eefbed8 Matt Todd Added Rack::Request initialization memoization to reduce repetitive inst...
mtodd authored
11 #
12 # The environment hash passed will store a reference to the Request object
13 # instantiated so that it will only instantiate if an instance of the Request
14 # object doesn't already exist.
230d62c Christian Neukirchen Fix trailing whitespace. Sigh.
chneukirchen authored
15
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
16 class Request
376fa1e Christian Neukirchen Add RDocs
chneukirchen authored
17 # The environment of the request.
05ab0f9 Christian Neukirchen More convenience for Rack::Request
chneukirchen authored
18 attr_reader :env
230d62c Christian Neukirchen Fix trailing whitespace. Sigh.
chneukirchen authored
19
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
20 def initialize(env)
21 @env = env
22 end
23
a18fc32 Christian Neukirchen Rename Request#method to #request_method to not confuse stdlibs
chneukirchen authored
24 def body; @env["rack.input"] end
25 def scheme; @env["rack.url_scheme"] end
26 def script_name; @env["SCRIPT_NAME"].to_s end
27 def path_info; @env["PATH_INFO"].to_s end
28 def port; @env["SERVER_PORT"].to_i end
29 def request_method; @env["REQUEST_METHOD"] end
166ab15 Christoffer Sawicki Add getter method for the query string (and use it internally)
qerub authored
30 def query_string; @env["QUERY_STRING"].to_s end
fe40ec2 Christian Neukirchen Fix that Request assumes form-data even when Content-Type says otherwise
chneukirchen authored
31 def content_length; @env['CONTENT_LENGTH'] end
32 def content_type; @env['CONTENT_TYPE'] end
e678c6a Joshua Peek Add 'rack.session' specification
josh authored
33 def session; @env['rack.session'] ||= {} end
34 def session_options; @env['rack.session.options'] ||= {} end
fe40ec2 Christian Neukirchen Fix that Request assumes form-data even when Content-Type says otherwise
chneukirchen authored
35
36 # The media type (type/subtype) portion of the CONTENT_TYPE header
37 # without any media type parameters. e.g., when CONTENT_TYPE is
38 # "text/plain;charset=utf-8", the media-type is "text/plain".
39 #
40 # For more information on the use of media types in HTTP, see:
41 # http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7
42 def media_type
939fa7d TJ Holowaychuk Refactored Rack::Request#media_type
tj authored
43 content_type && content_type.split(/\s*[;,]\s*/, 2).first.downcase
fe40ec2 Christian Neukirchen Fix that Request assumes form-data even when Content-Type says otherwise
chneukirchen authored
44 end
45
46 # The media type parameters provided in CONTENT_TYPE as a Hash, or
47 # an empty Hash if no CONTENT_TYPE or media-type parameters were
48 # provided. e.g., when the CONTENT_TYPE is "text/plain;charset=utf-8",
49 # this method responds with the following Hash:
50 # { 'charset' => 'utf-8' }
51 def media_type_params
52 return {} if content_type.nil?
53 content_type.split(/\s*[;,]\s*/)[1..-1].
54 collect { |s| s.split('=', 2) }.
55 inject({}) { |hash,(k,v)| hash[k.downcase] = v ; hash }
56 end
57
58 # The character set of the request body if a "charset" media type
59 # parameter was given, or nil if no "charset" was specified. Note
60 # that, per RFC2616, text/* media types that specify no explicit
61 # charset are to be considered ISO-8859-1.
62 def content_charset
63 media_type_params['charset']
64 end
a18fc32 Christian Neukirchen Rename Request#method to #request_method to not confuse stdlibs
chneukirchen authored
65
c95b751 Christian Neukirchen Remove the port number of HTTP_HOST and SERVER_NAME
chneukirchen authored
66 def host
67 # Remove port number.
488cf80 Joshua Peek Return an empty string for Request#host if HTTP_HOST and SERVER_NAME are...
josh authored
68 (@env["HTTP_HOST"] || @env["SERVER_NAME"]).to_s.gsub(/:\d+\z/, '')
c95b751 Christian Neukirchen Remove the port number of HTTP_HOST and SERVER_NAME
chneukirchen authored
69 end
70
a18fc32 Christian Neukirchen Rename Request#method to #request_method to not confuse stdlibs
chneukirchen authored
71 def script_name=(s); @env["SCRIPT_NAME"] = s.to_s end
72 def path_info=(s); @env["PATH_INFO"] = s.to_s end
73
74 def get?; request_method == "GET" end
75 def post?; request_method == "POST" end
76 def put?; request_method == "PUT" end
77 def delete?; request_method == "DELETE" end
fe40ec2 Christian Neukirchen Fix that Request assumes form-data even when Content-Type says otherwise
chneukirchen authored
78 def head?; request_method == "HEAD" end
79
80 # The set of form-data media-types. Requests that do not indicate
81 # one of the media types presents in this list will not be eligible
82 # for form-data / param parsing.
83 FORM_DATA_MEDIA_TYPES = [
84 nil,
85 'application/x-www-form-urlencoded',
86 'multipart/form-data'
87 ]
88
6674f36 better multipart handling
eTM authored
89 # The set of media-types. Requests that do not indicate
90 # one of the media types presents in this list will not be eligible
91 # for param parsing like soap attachments or generic multiparts
92 PARSEABLE_DATA_MEDIA_TYPES = [
93 'multipart/related',
94 'multipart/mixed'
95 ]
96
fe40ec2 Christian Neukirchen Fix that Request assumes form-data even when Content-Type says otherwise
chneukirchen authored
97 # Determine whether the request body contains form-data by checking
98 # the request media_type against registered form-data media-types:
99 # "application/x-www-form-urlencoded" and "multipart/form-data". The
100 # list of form-data media types can be modified through the
101 # +FORM_DATA_MEDIA_TYPES+ array.
102 def form_data?
103 FORM_DATA_MEDIA_TYPES.include?(media_type)
104 end
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
105
6674f36 better multipart handling
eTM authored
106 # Determine whether the request body contains data by checking
107 # the request media_type against registered parse-data media-types
108 def parseable_data?
109 PARSEABLE_DATA_MEDIA_TYPES.include?(media_type)
110 end
111
376fa1e Christian Neukirchen Add RDocs
chneukirchen authored
112 # Returns the data recieved in the query string.
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
113 def GET
166ab15 Christoffer Sawicki Add getter method for the query string (and use it internally)
qerub authored
114 if @env["rack.request.query_string"] == query_string
6c80c6c Christian Neukirchen Cache the parsed things in Rack::Request
chneukirchen authored
115 @env["rack.request.query_hash"]
116 else
166ab15 Christoffer Sawicki Add getter method for the query string (and use it internally)
qerub authored
117 @env["rack.request.query_string"] = query_string
118 @env["rack.request.query_hash"] =
5c00dd6 Joshua Peek Split parse_query utility into parse_query and parse_nested_query. parse...
josh authored
119 Utils.parse_nested_query(query_string)
6c80c6c Christian Neukirchen Cache the parsed things in Rack::Request
chneukirchen authored
120 end
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
121 end
122
376fa1e Christian Neukirchen Add RDocs
chneukirchen authored
123 # Returns the data recieved in the request body.
124 #
125 # This method support both application/x-www-form-urlencoded and
126 # multipart/form-data.
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
127 def POST
7f34329 Bug fix for Tempfile POST bodies under Ruby 1.8
Adam Harper authored
128 if @env["rack.request.form_input"].eql? @env["rack.input"]
6c80c6c Christian Neukirchen Cache the parsed things in Rack::Request
chneukirchen authored
129 @env["rack.request.form_hash"]
6674f36 better multipart handling
eTM authored
130 elsif form_data? || parseable_data?
6c80c6c Christian Neukirchen Cache the parsed things in Rack::Request
chneukirchen authored
131 @env["rack.request.form_input"] = @env["rack.input"]
4fe5360 Christian Neukirchen Make Rack::Request read multipart form data
chneukirchen authored
132 unless @env["rack.request.form_hash"] =
230d62c Christian Neukirchen Fix trailing whitespace. Sigh.
chneukirchen authored
133 Utils::Multipart.parse_multipart(env)
0f081dd Joshua Peek Clean up Safari's ajax POST body
josh authored
134 form_vars = @env["rack.input"].read
135
136 # Fix for Safari Ajax postings that always append \0
137 form_vars.sub!(/\0\z/, '')
138
139 @env["rack.request.form_vars"] = form_vars
5c00dd6 Joshua Peek Split parse_query utility into parse_query and parse_nested_query. parse...
josh authored
140 @env["rack.request.form_hash"] = Utils.parse_nested_query(form_vars)
3513f4f Joshua Peek Add tests for multipart uploads. Also ensure multipart parser tries to r...
josh authored
141
95f068e Hongli Lai Remove code for handling the possibility that rack.input may not be rewi...
FooBarWidget authored
142 @env["rack.input"].rewind
4fe5360 Christian Neukirchen Make Rack::Request read multipart form data
chneukirchen authored
143 end
144 @env["rack.request.form_hash"]
fe40ec2 Christian Neukirchen Fix that Request assumes form-data even when Content-Type says otherwise
chneukirchen authored
145 else
146 {}
6c80c6c Christian Neukirchen Cache the parsed things in Rack::Request
chneukirchen authored
147 end
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
148 end
149
376fa1e Christian Neukirchen Add RDocs
chneukirchen authored
150 # The union of GET and POST data.
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
151 def params
8d01dc0 Avoid slurping or parsing request body on PUT requests
Eric Wong authored
152 self.put? ? self.GET : self.GET.update(self.POST)
67a7507 Christian Neukirchen handle EOFError exception in Request#params
chneukirchen authored
153 rescue EOFError => e
154 self.GET
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
155 end
156
de7411c Michael Fellinger add some features to Request and the corresponding tests for them
manveru authored
157 # shortcut for request.params[key]
158 def [](key)
159 params[key.to_s]
160 end
161
162 # shortcut for request.params[key] = value
163 def []=(key, value)
164 params[key.to_s] = value
165 end
166
167 # like Hash#values_at
168 def values_at(*keys)
169 keys.map{|key| params[key] }
170 end
171
172 # the referer of the client or '/'
173 def referer
174 @env['HTTP_REFERER'] || '/'
175 end
176 alias referrer referer
177
178
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
179 def cookies
b68c2d5 Christian Neukirchen Return empty hash on lack of cookies
chneukirchen authored
180 return {} unless @env["HTTP_COOKIE"]
181
6c80c6c Christian Neukirchen Cache the parsed things in Rack::Request
chneukirchen authored
182 if @env["rack.request.cookie_string"] == @env["HTTP_COOKIE"]
183 @env["rack.request.cookie_hash"]
184 else
185 @env["rack.request.cookie_string"] = @env["HTTP_COOKIE"]
4a08f8a Conform to RFC 2109 regarding multiple values for same cookie
Aman Gupta authored
186 # According to RFC 2109:
187 # If multiple cookies satisfy the criteria above, they are ordered in
188 # the Cookie header such that those with more specific Path attributes
189 # precede those with less specific. Ordering with respect to other
190 # attributes (e.g., Domain) is unspecified.
6c80c6c Christian Neukirchen Cache the parsed things in Rack::Request
chneukirchen authored
191 @env["rack.request.cookie_hash"] =
4a08f8a Conform to RFC 2109 regarding multiple values for same cookie
Aman Gupta authored
192 Utils.parse_query(@env["rack.request.cookie_string"], ';,').inject({}) {|h,(k,v)|
acb8695 Christian Neukirchen Fix cookie parsing
chneukirchen authored
193 h[k] = Array === v ? v.first : v
4a08f8a Conform to RFC 2109 regarding multiple values for same cookie
Aman Gupta authored
194 h
195 }
6c80c6c Christian Neukirchen Cache the parsed things in Rack::Request
chneukirchen authored
196 end
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
197 end
198
199 def xhr?
200 @env["HTTP_X_REQUESTED_WITH"] == "XMLHttpRequest"
201 end
fd51d36 Christian Neukirchen Add Request#url
chneukirchen authored
202
376fa1e Christian Neukirchen Add RDocs
chneukirchen authored
203 # Tries to return a remake of the original request URL as a string.
fd51d36 Christian Neukirchen Add Request#url
chneukirchen authored
204 def url
205 url = scheme + "://"
206 url << host
207
208 if scheme == "https" && port != 443 ||
209 scheme == "http" && port != 80
210 url << ":#{port}"
211 end
212
234c062 Christian Neukirchen Add Request#fullpath
chneukirchen authored
213 url << fullpath
fd51d36 Christian Neukirchen Add Request#url
chneukirchen authored
214
215 url
216 end
3a544a7 TJ Holowaychuk Added Rack::Request#path
tj authored
217
218 def path
219 script_name + path_info
220 end
221
234c062 Christian Neukirchen Add Request#fullpath
chneukirchen authored
222 def fullpath
3a544a7 TJ Holowaychuk Added Rack::Request#path
tj authored
223 query_string.empty? ? path : "#{path}?#{query_string}"
234c062 Christian Neukirchen Add Request#fullpath
chneukirchen authored
224 end
0f2dab5 Christoffer Sawicki Added support for Accept-Encoding (via Request#accept_encoding and Utils...
qerub authored
225
226 def accept_encoding
227 @env["HTTP_ACCEPT_ENCODING"].to_s.split(/,\s*/).map do |part|
228 m = /^([^\s,]+?)(?:;\s*q=(\d+(?:\.\d+)?))?$/.match(part) # From WEBrick
229
230 if m
231 [m[1], (m[2] || 1.0).to_f]
232 else
233 raise "Invalid value for Accept-Encoding: #{part.inspect}"
234 end
235 end
236 end
a48eb51 Michael Fellinger Add Request#ip and corresponding spec
manveru authored
237
238 def ip
239 if addr = @env['HTTP_X_FORWARDED_FOR']
240 addr.split(',').last.strip
241 else
242 @env['REMOTE_ADDR']
243 end
244 end
5f13e3d Christian Neukirchen Add Rack::Request
chneukirchen authored
245 end
246 end
Something went wrong with that request. Please try again.