rack 1.4.7 → 2.1.4

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rack might be problematic. Click here for more details.

Files changed (183) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +77 -0
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +122 -456
  5. data/Rakefile +32 -31
  6. data/SPEC +119 -29
  7. data/bin/rackup +1 -0
  8. data/contrib/rack_logo.svg +164 -111
  9. data/example/lobster.ru +2 -0
  10. data/example/protectedlobster.rb +4 -2
  11. data/example/protectedlobster.ru +3 -1
  12. data/lib/rack/auth/abstract/handler.rb +7 -5
  13. data/lib/rack/auth/abstract/request.rb +8 -6
  14. data/lib/rack/auth/basic.rb +5 -2
  15. data/lib/rack/auth/digest/md5.rb +10 -8
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +5 -4
  18. data/lib/rack/auth/digest/request.rb +4 -2
  19. data/lib/rack/body_proxy.rb +11 -9
  20. data/lib/rack/builder.rb +63 -20
  21. data/lib/rack/cascade.rb +10 -9
  22. data/lib/rack/chunked.rb +45 -11
  23. data/lib/rack/{commonlogger.rb → common_logger.rb} +24 -15
  24. data/lib/rack/{conditionalget.rb → conditional_get.rb} +20 -6
  25. data/lib/rack/config.rb +7 -0
  26. data/lib/rack/content_length.rb +12 -6
  27. data/lib/rack/content_type.rb +4 -2
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +73 -42
  30. data/lib/rack/directory.rb +77 -56
  31. data/lib/rack/etag.rb +25 -13
  32. data/lib/rack/events.rb +156 -0
  33. data/lib/rack/file.rb +4 -143
  34. data/lib/rack/files.rb +178 -0
  35. data/lib/rack/handler/cgi.rb +18 -17
  36. data/lib/rack/handler/fastcgi.rb +21 -17
  37. data/lib/rack/handler/lsws.rb +14 -12
  38. data/lib/rack/handler/scgi.rb +27 -21
  39. data/lib/rack/handler/thin.rb +19 -5
  40. data/lib/rack/handler/webrick.rb +66 -24
  41. data/lib/rack/handler.rb +29 -19
  42. data/lib/rack/head.rb +21 -14
  43. data/lib/rack/lint.rb +259 -65
  44. data/lib/rack/lobster.rb +17 -10
  45. data/lib/rack/lock.rb +19 -10
  46. data/lib/rack/logger.rb +4 -2
  47. data/lib/rack/media_type.rb +43 -0
  48. data/lib/rack/method_override.rb +52 -0
  49. data/lib/rack/mime.rb +43 -6
  50. data/lib/rack/mock.rb +109 -44
  51. data/lib/rack/multipart/generator.rb +11 -12
  52. data/lib/rack/multipart/parser.rb +302 -115
  53. data/lib/rack/multipart/uploaded_file.rb +4 -3
  54. data/lib/rack/multipart.rb +40 -9
  55. data/lib/rack/null_logger.rb +39 -0
  56. data/lib/rack/query_parser.rb +218 -0
  57. data/lib/rack/recursive.rb +14 -11
  58. data/lib/rack/reloader.rb +12 -5
  59. data/lib/rack/request.rb +484 -270
  60. data/lib/rack/response.rb +196 -77
  61. data/lib/rack/rewindable_input.rb +5 -14
  62. data/lib/rack/runtime.rb +13 -6
  63. data/lib/rack/sendfile.rb +44 -20
  64. data/lib/rack/server.rb +175 -61
  65. data/lib/rack/session/abstract/id.rb +276 -133
  66. data/lib/rack/session/cookie.rb +75 -40
  67. data/lib/rack/session/memcache.rb +4 -87
  68. data/lib/rack/session/pool.rb +24 -18
  69. data/lib/rack/show_exceptions.rb +392 -0
  70. data/lib/rack/{showstatus.rb → show_status.rb} +11 -9
  71. data/lib/rack/static.rb +65 -38
  72. data/lib/rack/tempfile_reaper.rb +24 -0
  73. data/lib/rack/urlmap.rb +40 -15
  74. data/lib/rack/utils.rb +316 -285
  75. data/lib/rack.rb +78 -23
  76. data/rack.gemspec +26 -19
  77. metadata +44 -209
  78. data/KNOWN-ISSUES +0 -30
  79. data/lib/rack/backports/uri/common_18.rb +0 -56
  80. data/lib/rack/backports/uri/common_192.rb +0 -52
  81. data/lib/rack/backports/uri/common_193.rb +0 -29
  82. data/lib/rack/handler/evented_mongrel.rb +0 -8
  83. data/lib/rack/handler/mongrel.rb +0 -100
  84. data/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  85. data/lib/rack/methodoverride.rb +0 -33
  86. data/lib/rack/nulllogger.rb +0 -18
  87. data/lib/rack/showexceptions.rb +0 -378
  88. data/test/builder/anything.rb +0 -5
  89. data/test/builder/comment.ru +0 -4
  90. data/test/builder/end.ru +0 -5
  91. data/test/builder/line.ru +0 -1
  92. data/test/builder/options.ru +0 -2
  93. data/test/cgi/assets/folder/test.js +0 -1
  94. data/test/cgi/assets/fonts/font.eot +0 -1
  95. data/test/cgi/assets/images/image.png +0 -1
  96. data/test/cgi/assets/index.html +0 -1
  97. data/test/cgi/assets/javascripts/app.js +0 -1
  98. data/test/cgi/assets/stylesheets/app.css +0 -1
  99. data/test/cgi/lighttpd.conf +0 -26
  100. data/test/cgi/lighttpd.errors +0 -1
  101. data/test/cgi/rackup_stub.rb +0 -6
  102. data/test/cgi/sample_rackup.ru +0 -5
  103. data/test/cgi/test +0 -9
  104. data/test/cgi/test+directory/test+file +0 -1
  105. data/test/cgi/test.fcgi +0 -8
  106. data/test/cgi/test.ru +0 -5
  107. data/test/gemloader.rb +0 -10
  108. data/test/multipart/bad_robots +0 -259
  109. data/test/multipart/binary +0 -0
  110. data/test/multipart/content_type_and_no_filename +0 -6
  111. data/test/multipart/empty +0 -10
  112. data/test/multipart/fail_16384_nofile +0 -814
  113. data/test/multipart/file1.txt +0 -1
  114. data/test/multipart/filename_and_modification_param +0 -7
  115. data/test/multipart/filename_with_escaped_quotes +0 -6
  116. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  117. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  118. data/test/multipart/filename_with_unescaped_percentages +0 -6
  119. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  120. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  121. data/test/multipart/filename_with_unescaped_quotes +0 -6
  122. data/test/multipart/ie +0 -6
  123. data/test/multipart/mixed_files +0 -21
  124. data/test/multipart/nested +0 -10
  125. data/test/multipart/none +0 -9
  126. data/test/multipart/semicolon +0 -6
  127. data/test/multipart/text +0 -15
  128. data/test/multipart/three_files_three_fields +0 -31
  129. data/test/multipart/webkit +0 -32
  130. data/test/rackup/config.ru +0 -31
  131. data/test/registering_handler/rack/handler/registering_myself.rb +0 -8
  132. data/test/spec_auth.rb +0 -57
  133. data/test/spec_auth_basic.rb +0 -81
  134. data/test/spec_auth_digest.rb +0 -259
  135. data/test/spec_body_proxy.rb +0 -69
  136. data/test/spec_builder.rb +0 -207
  137. data/test/spec_cascade.rb +0 -61
  138. data/test/spec_cgi.rb +0 -102
  139. data/test/spec_chunked.rb +0 -87
  140. data/test/spec_commonlogger.rb +0 -57
  141. data/test/spec_conditionalget.rb +0 -102
  142. data/test/spec_config.rb +0 -22
  143. data/test/spec_content_length.rb +0 -86
  144. data/test/spec_content_type.rb +0 -45
  145. data/test/spec_deflater.rb +0 -187
  146. data/test/spec_directory.rb +0 -88
  147. data/test/spec_etag.rb +0 -98
  148. data/test/spec_fastcgi.rb +0 -107
  149. data/test/spec_file.rb +0 -200
  150. data/test/spec_handler.rb +0 -59
  151. data/test/spec_head.rb +0 -48
  152. data/test/spec_lint.rb +0 -515
  153. data/test/spec_lobster.rb +0 -58
  154. data/test/spec_lock.rb +0 -167
  155. data/test/spec_logger.rb +0 -23
  156. data/test/spec_methodoverride.rb +0 -72
  157. data/test/spec_mock.rb +0 -269
  158. data/test/spec_mongrel.rb +0 -182
  159. data/test/spec_multipart.rb +0 -479
  160. data/test/spec_nulllogger.rb +0 -23
  161. data/test/spec_recursive.rb +0 -72
  162. data/test/spec_request.rb +0 -955
  163. data/test/spec_response.rb +0 -313
  164. data/test/spec_rewindable_input.rb +0 -118
  165. data/test/spec_runtime.rb +0 -49
  166. data/test/spec_sendfile.rb +0 -90
  167. data/test/spec_server.rb +0 -121
  168. data/test/spec_session_abstract_id.rb +0 -43
  169. data/test/spec_session_cookie.rb +0 -361
  170. data/test/spec_session_memcache.rb +0 -321
  171. data/test/spec_session_pool.rb +0 -209
  172. data/test/spec_showexceptions.rb +0 -92
  173. data/test/spec_showstatus.rb +0 -84
  174. data/test/spec_static.rb +0 -145
  175. data/test/spec_thin.rb +0 -86
  176. data/test/spec_urlmap.rb +0 -213
  177. data/test/spec_utils.rb +0 -554
  178. data/test/spec_webrick.rb +0 -143
  179. data/test/static/another/index.html +0 -1
  180. data/test/static/index.html +0 -1
  181. data/test/testrequest.rb +0 -78
  182. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  183. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
data/test/spec_request.rb DELETED
@@ -1,955 +0,0 @@
1
- require 'stringio'
2
- require 'cgi'
3
- require 'rack/request'
4
- require 'rack/mock'
5
- require 'securerandom'
6
-
7
- describe Rack::Request do
8
- should "wrap the rack variables" do
9
- req = Rack::Request.new(Rack::MockRequest.env_for("http://example.com:8080/"))
10
-
11
- req.body.should.respond_to? :gets
12
- req.scheme.should.equal "http"
13
- req.request_method.should.equal "GET"
14
-
15
- req.should.be.get
16
- req.should.not.be.post
17
- req.should.not.be.put
18
- req.should.not.be.delete
19
- req.should.not.be.head
20
- req.should.not.be.patch
21
-
22
- req.script_name.should.equal ""
23
- req.path_info.should.equal "/"
24
- req.query_string.should.equal ""
25
-
26
- req.host.should.equal "example.com"
27
- req.port.should.equal 8080
28
-
29
- req.content_length.should.equal "0"
30
- req.content_type.should.be.nil
31
- end
32
-
33
- should "figure out the correct host" do
34
- req = Rack::Request.new \
35
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
36
- req.host.should.equal "www2.example.org"
37
-
38
- req = Rack::Request.new \
39
- Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
40
- req.host.should.equal "example.org"
41
-
42
- req = Rack::Request.new \
43
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
44
- req.host.should.equal "example.org"
45
-
46
- env = Rack::MockRequest.env_for("/", "SERVER_ADDR" => "192.168.1.1", "SERVER_PORT" => "9292")
47
- env.delete("SERVER_NAME")
48
- req = Rack::Request.new(env)
49
- req.host.should.equal "192.168.1.1"
50
-
51
- env = Rack::MockRequest.env_for("/")
52
- env.delete("SERVER_NAME")
53
- req = Rack::Request.new(env)
54
- req.host.should.equal ""
55
- end
56
-
57
- should "figure out the correct port" do
58
- req = Rack::Request.new \
59
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
60
- req.port.should.equal 80
61
-
62
- req = Rack::Request.new \
63
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org:81")
64
- req.port.should.equal 81
65
-
66
- req = Rack::Request.new \
67
- Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
68
- req.port.should.equal 9292
69
-
70
- req = Rack::Request.new \
71
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
72
- req.port.should.equal 9292
73
-
74
- req = Rack::Request.new \
75
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org")
76
- req.port.should.equal 80
77
-
78
- req = Rack::Request.new \
79
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_SSL" => "on")
80
- req.port.should.equal 443
81
-
82
- req = Rack::Request.new \
83
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PROTO" => "https")
84
- req.port.should.equal 443
85
-
86
- req = Rack::Request.new \
87
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PORT" => "9393")
88
- req.port.should.equal 9393
89
-
90
- req = Rack::Request.new \
91
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9393", "SERVER_PORT" => "80")
92
- req.port.should.equal 9393
93
-
94
- req = Rack::Request.new \
95
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393")
96
- req.port.should.equal 80
97
- end
98
-
99
- should "figure out the correct host with port" do
100
- req = Rack::Request.new \
101
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
102
- req.host_with_port.should.equal "www2.example.org"
103
-
104
- req = Rack::Request.new \
105
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81")
106
- req.host_with_port.should.equal "localhost:81"
107
-
108
- req = Rack::Request.new \
109
- Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
110
- req.host_with_port.should.equal "example.org:9292"
111
-
112
- req = Rack::Request.new \
113
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
114
- req.host_with_port.should.equal "example.org:9292"
115
-
116
- req = Rack::Request.new \
117
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393")
118
- req.host_with_port.should.equal "example.org"
119
- end
120
-
121
- should "parse the query string" do
122
- req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
123
- req.query_string.should.equal "foo=bar&quux=bla"
124
- req.GET.should.equal "foo" => "bar", "quux" => "bla"
125
- req.POST.should.be.empty
126
- req.params.should.equal "foo" => "bar", "quux" => "bla"
127
- end
128
-
129
- should "limit the keys from the GET query string" do
130
- env = Rack::MockRequest.env_for("/?foo=bar")
131
-
132
- old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
133
- begin
134
- req = Rack::Request.new(env)
135
- lambda { req.GET }.should.raise(RangeError)
136
- ensure
137
- Rack::Utils.key_space_limit = old
138
- end
139
- end
140
-
141
- should "limit the key size per nested params hash" do
142
- nested_query = Rack::MockRequest.env_for("/?foo[bar][baz][qux]=1")
143
- plain_query = Rack::MockRequest.env_for("/?foo_bar__baz__qux_=1")
144
-
145
- old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 3
146
- begin
147
- lambda { Rack::Request.new(nested_query).GET }.should.not.raise(RangeError)
148
- lambda { Rack::Request.new(plain_query).GET }.should.raise(RangeError)
149
- ensure
150
- Rack::Utils.key_space_limit = old
151
- end
152
- end
153
-
154
- should "not unify GET and POST when calling params" do
155
- mr = Rack::MockRequest.env_for("/?foo=quux",
156
- "REQUEST_METHOD" => 'POST',
157
- :input => "foo=bar&quux=bla"
158
- )
159
- req = Rack::Request.new mr
160
-
161
- req.params
162
-
163
- req.GET.should.equal "foo" => "quux"
164
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
165
- req.params.should.equal req.GET.merge(req.POST)
166
- end
167
-
168
- should "raise if rack.input is missing" do
169
- req = Rack::Request.new({})
170
- lambda { req.POST }.should.raise(RuntimeError)
171
- end
172
-
173
- should "parse POST data when method is POST and no Content-Type given" do
174
- req = Rack::Request.new \
175
- Rack::MockRequest.env_for("/?foo=quux",
176
- "REQUEST_METHOD" => 'POST',
177
- :input => "foo=bar&quux=bla")
178
- req.content_type.should.be.nil
179
- req.media_type.should.be.nil
180
- req.query_string.should.equal "foo=quux"
181
- req.GET.should.equal "foo" => "quux"
182
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
183
- req.params.should.equal "foo" => "bar", "quux" => "bla"
184
- end
185
-
186
- should "limit the keys from the POST form data" do
187
- env = Rack::MockRequest.env_for("",
188
- "REQUEST_METHOD" => 'POST',
189
- :input => "foo=bar&quux=bla")
190
-
191
- old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
192
- begin
193
- req = Rack::Request.new(env)
194
- lambda { req.POST }.should.raise(RangeError)
195
- ensure
196
- Rack::Utils.key_space_limit = old
197
- end
198
- end
199
-
200
- should "parse POST data with explicit content type regardless of method" do
201
- req = Rack::Request.new \
202
- Rack::MockRequest.env_for("/",
203
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
204
- :input => "foo=bar&quux=bla")
205
- req.content_type.should.equal 'application/x-www-form-urlencoded;foo=bar'
206
- req.media_type.should.equal 'application/x-www-form-urlencoded'
207
- req.media_type_params['foo'].should.equal 'bar'
208
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
209
- req.params.should.equal "foo" => "bar", "quux" => "bla"
210
- end
211
-
212
- should "not parse POST data when media type is not form-data" do
213
- req = Rack::Request.new \
214
- Rack::MockRequest.env_for("/?foo=quux",
215
- "REQUEST_METHOD" => 'POST',
216
- "CONTENT_TYPE" => 'text/plain;charset=utf-8',
217
- :input => "foo=bar&quux=bla")
218
- req.content_type.should.equal 'text/plain;charset=utf-8'
219
- req.media_type.should.equal 'text/plain'
220
- req.media_type_params['charset'].should.equal 'utf-8'
221
- req.POST.should.be.empty
222
- req.params.should.equal "foo" => "quux"
223
- req.body.read.should.equal "foo=bar&quux=bla"
224
- end
225
-
226
- should "parse POST data on PUT when media type is form-data" do
227
- req = Rack::Request.new \
228
- Rack::MockRequest.env_for("/?foo=quux",
229
- "REQUEST_METHOD" => 'PUT',
230
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded',
231
- :input => "foo=bar&quux=bla")
232
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
233
- req.body.read.should.equal "foo=bar&quux=bla"
234
- end
235
-
236
- should "rewind input after parsing POST data" do
237
- input = StringIO.new("foo=bar&quux=bla")
238
- req = Rack::Request.new \
239
- Rack::MockRequest.env_for("/",
240
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
241
- :input => input)
242
- req.params.should.equal "foo" => "bar", "quux" => "bla"
243
- input.read.should.equal "foo=bar&quux=bla"
244
- end
245
-
246
- should "clean up Safari's ajax POST body" do
247
- req = Rack::Request.new \
248
- Rack::MockRequest.env_for("/",
249
- 'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0")
250
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
251
- end
252
-
253
- should "get value by key from params with #[]" do
254
- req = Rack::Request.new \
255
- Rack::MockRequest.env_for("?foo=quux")
256
- req['foo'].should.equal 'quux'
257
- req[:foo].should.equal 'quux'
258
- end
259
-
260
- should "set value to key on params with #[]=" do
261
- req = Rack::Request.new \
262
- Rack::MockRequest.env_for("?foo=duh")
263
- req['foo'].should.equal 'duh'
264
- req[:foo].should.equal 'duh'
265
- req.params.should.equal 'foo' => 'duh'
266
-
267
- req['foo'] = 'bar'
268
- req.params.should.equal 'foo' => 'bar'
269
- req['foo'].should.equal 'bar'
270
- req[:foo].should.equal 'bar'
271
-
272
- req[:foo] = 'jaz'
273
- req.params.should.equal 'foo' => 'jaz'
274
- req['foo'].should.equal 'jaz'
275
- req[:foo].should.equal 'jaz'
276
- end
277
-
278
- should "return values for the keys in the order given from values_at" do
279
- req = Rack::Request.new \
280
- Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful")
281
- req.values_at('foo').should.equal ['baz']
282
- req.values_at('foo', 'wun').should.equal ['baz', 'der']
283
- req.values_at('bar', 'foo', 'wun').should.equal ['ful', 'baz', 'der']
284
- end
285
-
286
- should "extract referrer correctly" do
287
- req = Rack::Request.new \
288
- Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path")
289
- req.referer.should.equal "/some/path"
290
-
291
- req = Rack::Request.new \
292
- Rack::MockRequest.env_for("/")
293
- req.referer.should.equal nil
294
- end
295
-
296
- should "extract user agent correctly" do
297
- req = Rack::Request.new \
298
- Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)")
299
- req.user_agent.should.equal "Mozilla/4.0 (compatible)"
300
-
301
- req = Rack::Request.new \
302
- Rack::MockRequest.env_for("/")
303
- req.user_agent.should.equal nil
304
- end
305
-
306
- should "treat missing content type as nil" do
307
- req = Rack::Request.new \
308
- Rack::MockRequest.env_for("/")
309
- req.content_type.should.equal nil
310
- end
311
-
312
- should "treat empty content type as nil" do
313
- req = Rack::Request.new \
314
- Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
315
- req.content_type.should.equal nil
316
- end
317
-
318
- should "return nil media type for empty content type" do
319
- req = Rack::Request.new \
320
- Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
321
- req.media_type.should.equal nil
322
- end
323
-
324
- should "cache, but invalidates the cache" do
325
- req = Rack::Request.new \
326
- Rack::MockRequest.env_for("/?foo=quux",
327
- "CONTENT_TYPE" => "application/x-www-form-urlencoded",
328
- :input => "foo=bar&quux=bla")
329
- req.GET.should.equal "foo" => "quux"
330
- req.GET.should.equal "foo" => "quux"
331
- req.env["QUERY_STRING"] = "bla=foo"
332
- req.GET.should.equal "bla" => "foo"
333
- req.GET.should.equal "bla" => "foo"
334
-
335
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
336
- req.POST.should.equal "foo" => "bar", "quux" => "bla"
337
- req.env["rack.input"] = StringIO.new("foo=bla&quux=bar")
338
- req.POST.should.equal "foo" => "bla", "quux" => "bar"
339
- req.POST.should.equal "foo" => "bla", "quux" => "bar"
340
- end
341
-
342
- should "figure out if called via XHR" do
343
- req = Rack::Request.new(Rack::MockRequest.env_for(""))
344
- req.should.not.be.xhr
345
-
346
- req = Rack::Request.new \
347
- Rack::MockRequest.env_for("", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest")
348
- req.should.be.xhr
349
- end
350
-
351
- should "ssl detection" do
352
- request = Rack::Request.new(Rack::MockRequest.env_for("/"))
353
- request.scheme.should.equal "http"
354
- request.should.not.be.ssl?
355
-
356
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTPS' => 'on'))
357
- request.scheme.should.equal "https"
358
- request.should.be.ssl?
359
-
360
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'rack.url_scheme' => 'https'))
361
- request.scheme.should.equal "https"
362
- request.should.be.ssl?
363
-
364
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8080'))
365
- request.scheme.should.equal "http"
366
- request.should.not.be.ssl?
367
-
368
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTPS' => 'on'))
369
- request.scheme.should.equal "https"
370
- request.should.be.ssl?
371
-
372
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTP_X_FORWARDED_SSL' => 'on'))
373
- request.scheme.should.equal "https"
374
- request.should.be.ssl?
375
-
376
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_SCHEME' => 'https'))
377
- request.scheme.should.equal "https"
378
- request.should.be.ssl?
379
-
380
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https'))
381
- request.scheme.should.equal "https"
382
- request.should.be.ssl?
383
-
384
- request = Rack::Request.new(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https, http, http'))
385
- request.scheme.should.equal "https"
386
- request.should.be.ssl?
387
- end
388
-
389
- should "parse cookies" do
390
- req = Rack::Request.new \
391
- Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
392
- req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
393
- req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
394
- req.env.delete("HTTP_COOKIE")
395
- req.cookies.should.equal({})
396
- end
397
-
398
- should "always return the same hash object" do
399
- req = Rack::Request.new \
400
- Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
401
- hash = req.cookies
402
- req.env.delete("HTTP_COOKIE")
403
- req.cookies.should.equal(hash)
404
- req.env["HTTP_COOKIE"] = "zoo=m"
405
- req.cookies.should.equal(hash)
406
- end
407
-
408
- should "modify the cookies hash in place" do
409
- req = Rack::Request.new(Rack::MockRequest.env_for(""))
410
- req.cookies.should.equal({})
411
- req.cookies['foo'] = 'bar'
412
- req.cookies.should.equal 'foo' => 'bar'
413
- end
414
-
415
- should "pass through non-uri escaped cookies as-is" do
416
- req = Rack::Request.new Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=%")
417
- req.cookies["foo"].should == "%"
418
- end
419
-
420
- should "parse cookies according to RFC 2109" do
421
- req = Rack::Request.new \
422
- Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car')
423
- req.cookies.should.equal 'foo' => 'bar'
424
- end
425
-
426
- should 'parse cookies with quotes' do
427
- req = Rack::Request.new Rack::MockRequest.env_for('', {
428
- 'HTTP_COOKIE' => '$Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"'
429
- })
430
- req.cookies.should.equal({
431
- '$Version' => '"1"',
432
- 'Customer' => '"WILE_E_COYOTE"',
433
- '$Path' => '"/acme"',
434
- 'Part_Number' => '"Rocket_Launcher_0001"',
435
- })
436
- end
437
-
438
- should "provide setters" do
439
- req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
440
- req.script_name.should.equal ""
441
- req.script_name = "/foo"
442
- req.script_name.should.equal "/foo"
443
- e["SCRIPT_NAME"].should.equal "/foo"
444
-
445
- req.path_info.should.equal "/"
446
- req.path_info = "/foo"
447
- req.path_info.should.equal "/foo"
448
- e["PATH_INFO"].should.equal "/foo"
449
- end
450
-
451
- should "provide the original env" do
452
- req = Rack::Request.new(e = Rack::MockRequest.env_for(""))
453
- req.env.should == e
454
- end
455
-
456
- should "restore the base URL" do
457
- Rack::Request.new(Rack::MockRequest.env_for("")).base_url.
458
- should.equal "http://example.org"
459
- Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).base_url.
460
- should.equal "http://example.org"
461
- end
462
-
463
- should "restore the URL" do
464
- Rack::Request.new(Rack::MockRequest.env_for("")).url.
465
- should.equal "http://example.org/"
466
- Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url.
467
- should.equal "http://example.org/foo/"
468
- Rack::Request.new(Rack::MockRequest.env_for("/foo")).url.
469
- should.equal "http://example.org/foo"
470
- Rack::Request.new(Rack::MockRequest.env_for("?foo")).url.
471
- should.equal "http://example.org/?foo"
472
- Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).url.
473
- should.equal "http://example.org:8080/"
474
- Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).url.
475
- should.equal "https://example.org/"
476
-
477
- Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).url.
478
- should.equal "https://example.com:8080/foo?foo"
479
- end
480
-
481
- should "restore the full path" do
482
- Rack::Request.new(Rack::MockRequest.env_for("")).fullpath.
483
- should.equal "/"
484
- Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath.
485
- should.equal "/foo/"
486
- Rack::Request.new(Rack::MockRequest.env_for("/foo")).fullpath.
487
- should.equal "/foo"
488
- Rack::Request.new(Rack::MockRequest.env_for("?foo")).fullpath.
489
- should.equal "/?foo"
490
- Rack::Request.new(Rack::MockRequest.env_for("http://example.org:8080/")).fullpath.
491
- should.equal "/"
492
- Rack::Request.new(Rack::MockRequest.env_for("https://example.org/")).fullpath.
493
- should.equal "/"
494
-
495
- Rack::Request.new(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).fullpath.
496
- should.equal "/foo?foo"
497
- end
498
-
499
- should "handle multiple media type parameters" do
500
- req = Rack::Request.new \
501
- Rack::MockRequest.env_for("/",
502
- "CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam')
503
- req.should.not.be.form_data
504
- req.media_type_params.should.include 'foo'
505
- req.media_type_params['foo'].should.equal 'BAR'
506
- req.media_type_params.should.include 'baz'
507
- req.media_type_params['baz'].should.equal 'bizzle dizzle'
508
- req.media_type_params.should.not.include 'BLING'
509
- req.media_type_params.should.include 'bling'
510
- req.media_type_params['bling'].should.equal 'bam'
511
- end
512
-
513
- should "parse with junk before boundry" do
514
- # Adapted from RFC 1867.
515
- input = <<EOF
516
- blah blah\r
517
- \r
518
- --AaB03x\r
519
- content-disposition: form-data; name="reply"\r
520
- \r
521
- yes\r
522
- --AaB03x\r
523
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
524
- Content-Type: image/jpeg\r
525
- Content-Transfer-Encoding: base64\r
526
- \r
527
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
528
- --AaB03x--\r
529
- EOF
530
- req = Rack::Request.new Rack::MockRequest.env_for("/",
531
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
532
- "CONTENT_LENGTH" => input.size,
533
- :input => input)
534
-
535
- req.POST.should.include "fileupload"
536
- req.POST.should.include "reply"
537
-
538
- req.should.be.form_data
539
- req.content_length.should.equal input.size
540
- req.media_type.should.equal 'multipart/form-data'
541
- req.media_type_params.should.include 'boundary'
542
- req.media_type_params['boundary'].should.equal 'AaB03x'
543
-
544
- req.POST["reply"].should.equal "yes"
545
-
546
- f = req.POST["fileupload"]
547
- f.should.be.kind_of Hash
548
- f[:type].should.equal "image/jpeg"
549
- f[:filename].should.equal "dj.jpg"
550
- f.should.include :tempfile
551
- f[:tempfile].size.should.equal 76
552
- end
553
-
554
- should "not infinite loop with a malformed HTTP request" do
555
- # Adapted from RFC 1867.
556
- input = <<EOF
557
- --AaB03x
558
- content-disposition: form-data; name="reply"
559
-
560
- yes
561
- --AaB03x
562
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"
563
- Content-Type: image/jpeg
564
- Content-Transfer-Encoding: base64
565
-
566
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg
567
- --AaB03x--
568
- EOF
569
- req = Rack::Request.new Rack::MockRequest.env_for("/",
570
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
571
- "CONTENT_LENGTH" => input.size,
572
- :input => input)
573
-
574
- lambda{req.POST}.should.raise(EOFError)
575
- end
576
-
577
-
578
- should "parse multipart form data" do
579
- # Adapted from RFC 1867.
580
- input = <<EOF
581
- --AaB03x\r
582
- content-disposition: form-data; name="reply"\r
583
- \r
584
- yes\r
585
- --AaB03x\r
586
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
587
- Content-Type: image/jpeg\r
588
- Content-Transfer-Encoding: base64\r
589
- \r
590
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
591
- --AaB03x--\r
592
- EOF
593
- req = Rack::Request.new Rack::MockRequest.env_for("/",
594
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
595
- "CONTENT_LENGTH" => input.size,
596
- :input => input)
597
-
598
- req.POST.should.include "fileupload"
599
- req.POST.should.include "reply"
600
-
601
- req.should.be.form_data
602
- req.content_length.should.equal input.size
603
- req.media_type.should.equal 'multipart/form-data'
604
- req.media_type_params.should.include 'boundary'
605
- req.media_type_params['boundary'].should.equal 'AaB03x'
606
-
607
- req.POST["reply"].should.equal "yes"
608
-
609
- f = req.POST["fileupload"]
610
- f.should.be.kind_of Hash
611
- f[:type].should.equal "image/jpeg"
612
- f[:filename].should.equal "dj.jpg"
613
- f.should.include :tempfile
614
- f[:tempfile].size.should.equal 76
615
- end
616
-
617
- should "MultipartLimitError when request has too many multipart parts if limit set" do
618
- begin
619
- data = 10000.times.map { "--AaB03x\r\nContent-Type: text/plain\r\nContent-Disposition: attachment; name=#{SecureRandom.hex(10)}; filename=#{SecureRandom.hex(10)}\r\n\r\ncontents\r\n" }.join("\r\n")
620
- data += "--AaB03x--\r"
621
-
622
- options = {
623
- "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
624
- "CONTENT_LENGTH" => data.length.to_s,
625
- :input => StringIO.new(data)
626
- }
627
-
628
- request = Rack::Request.new Rack::MockRequest.env_for("/", options)
629
- lambda { request.POST }.should.raise(Rack::Multipart::MultipartLimitError)
630
- end
631
- end
632
-
633
- should "parse big multipart form data" do
634
- input = <<EOF
635
- --AaB03x\r
636
- content-disposition: form-data; name="huge"; filename="huge"\r
637
- \r
638
- #{"x"*32768}\r
639
- --AaB03x\r
640
- content-disposition: form-data; name="mean"; filename="mean"\r
641
- \r
642
- --AaB03xha\r
643
- --AaB03x--\r
644
- EOF
645
- req = Rack::Request.new Rack::MockRequest.env_for("/",
646
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
647
- "CONTENT_LENGTH" => input.size,
648
- :input => input)
649
-
650
- req.POST["huge"][:tempfile].size.should.equal 32768
651
- req.POST["mean"][:tempfile].size.should.equal 10
652
- req.POST["mean"][:tempfile].read.should.equal "--AaB03xha"
653
- end
654
-
655
- should "detect invalid multipart form data" do
656
- input = <<EOF
657
- --AaB03x\r
658
- content-disposition: form-data; name="huge"; filename="huge"\r
659
- EOF
660
- req = Rack::Request.new Rack::MockRequest.env_for("/",
661
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
662
- "CONTENT_LENGTH" => input.size,
663
- :input => input)
664
-
665
- lambda { req.POST }.should.raise(EOFError)
666
-
667
- input = <<EOF
668
- --AaB03x\r
669
- content-disposition: form-data; name="huge"; filename="huge"\r
670
- \r
671
- foo\r
672
- EOF
673
- req = Rack::Request.new Rack::MockRequest.env_for("/",
674
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
675
- "CONTENT_LENGTH" => input.size,
676
- :input => input)
677
-
678
- lambda { req.POST }.should.raise(EOFError)
679
-
680
- input = <<EOF
681
- --AaB03x\r
682
- content-disposition: form-data; name="huge"; filename="huge"\r
683
- \r
684
- foo\r
685
- EOF
686
- req = Rack::Request.new Rack::MockRequest.env_for("/",
687
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
688
- "CONTENT_LENGTH" => input.size,
689
- :input => input)
690
-
691
- lambda { req.POST }.should.raise(EOFError)
692
- end
693
-
694
- should "correctly parse the part name from Content-Id header" do
695
- input = <<EOF
696
- --AaB03x\r
697
- Content-Type: text/xml; charset=utf-8\r
698
- Content-Id: <soap-start>\r
699
- Content-Transfer-Encoding: 7bit\r
700
- \r
701
- foo\r
702
- --AaB03x--\r
703
- EOF
704
- req = Rack::Request.new Rack::MockRequest.env_for("/",
705
- "CONTENT_TYPE" => "multipart/related, boundary=AaB03x",
706
- "CONTENT_LENGTH" => input.size,
707
- :input => input)
708
-
709
- req.params.keys.should.equal ["<soap-start>"]
710
- end
711
-
712
- should "not try to interpret binary as utf8" do
713
- if /regexp/.respond_to?(:kcode) # < 1.9
714
- begin
715
- original_kcode = $KCODE
716
- $KCODE='UTF8'
717
-
718
- input = <<EOF
719
- --AaB03x\r
720
- content-disposition: form-data; name="fileupload"; filename="junk.a"\r
721
- content-type: application/octet-stream\r
722
- \r
723
- #{[0x36,0xCF,0x0A,0xF8].pack('c*')}\r
724
- --AaB03x--\r
725
- EOF
726
-
727
- req = Rack::Request.new Rack::MockRequest.env_for("/",
728
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
729
- "CONTENT_LENGTH" => input.size,
730
- :input => input)
731
-
732
- lambda{req.POST}.should.not.raise(EOFError)
733
- req.POST["fileupload"][:tempfile].size.should.equal 4
734
- ensure
735
- $KCODE = original_kcode
736
- end
737
- else # >= 1.9
738
- input = <<EOF
739
- --AaB03x\r
740
- content-disposition: form-data; name="fileupload"; filename="junk.a"\r
741
- content-type: application/octet-stream\r
742
- \r
743
- #{[0x36,0xCF,0x0A,0xF8].pack('c*')}\r
744
- --AaB03x--\r
745
- EOF
746
-
747
- req = Rack::Request.new Rack::MockRequest.env_for("/",
748
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
749
- "CONTENT_LENGTH" => input.size,
750
- :input => input)
751
-
752
- lambda{req.POST}.should.not.raise(EOFError)
753
- req.POST["fileupload"][:tempfile].size.should.equal 4
754
- end
755
- end
756
-
757
- should "work around buggy 1.8.* Tempfile equality" do
758
- input = <<EOF
759
- --AaB03x\r
760
- content-disposition: form-data; name="huge"; filename="huge"\r
761
- \r
762
- foo\r
763
- --AaB03x--
764
- EOF
765
-
766
- rack_input = Tempfile.new("rackspec")
767
- rack_input.write(input)
768
- rack_input.rewind
769
-
770
- req = Rack::Request.new Rack::MockRequest.env_for("/",
771
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
772
- "CONTENT_LENGTH" => input.size,
773
- :input => rack_input)
774
-
775
- lambda{ req.POST }.should.not.raise
776
- lambda{ req.POST }.should.not.raise("input re-processed!")
777
- end
778
-
779
- should "conform to the Rack spec" do
780
- app = lambda { |env|
781
- content = Rack::Request.new(env).POST["file"].inspect
782
- size = content.respond_to?(:bytesize) ? content.bytesize : content.size
783
- [200, {"Content-Type" => "text/html", "Content-Length" => size.to_s}, [content]]
784
- }
785
-
786
- input = <<EOF
787
- --AaB03x\r
788
- content-disposition: form-data; name="reply"\r
789
- \r
790
- yes\r
791
- --AaB03x\r
792
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
793
- Content-Type: image/jpeg\r
794
- Content-Transfer-Encoding: base64\r
795
- \r
796
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
797
- --AaB03x--\r
798
- EOF
799
- input.force_encoding("ASCII-8BIT") if input.respond_to? :force_encoding
800
- res = Rack::MockRequest.new(Rack::Lint.new(app)).get "/",
801
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
802
- "CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input)
803
-
804
- res.should.be.ok
805
- end
806
-
807
- should "parse Accept-Encoding correctly" do
808
- parser = lambda do |x|
809
- Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
810
- end
811
-
812
- parser.call(nil).should.equal([])
813
-
814
- parser.call("compress, gzip").should.equal([["compress", 1.0], ["gzip", 1.0]])
815
- parser.call("").should.equal([])
816
- parser.call("*").should.equal([["*", 1.0]])
817
- parser.call("compress;q=0.5, gzip;q=1.0").should.equal([["compress", 0.5], ["gzip", 1.0]])
818
- parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").should.equal([["gzip", 1.0], ["identity", 0.5], ["*", 0] ])
819
-
820
- parser.call("gzip ; q=0.9").should.equal([["gzip", 0.9]])
821
- parser.call("gzip ; deflate").should.equal([["gzip", 1.0]])
822
- end
823
-
824
- ip_app = lambda { |env|
825
- request = Rack::Request.new(env)
826
- response = Rack::Response.new
827
- response.write request.ip
828
- response.finish
829
- }
830
-
831
- should 'provide ip information' do
832
- mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
833
-
834
- res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4'
835
- res.body.should.equal '1.2.3.4'
836
-
837
- res = mock.get '/', 'REMOTE_ADDR' => 'fe80::202:b3ff:fe1e:8329'
838
- res.body.should.equal 'fe80::202:b3ff:fe1e:8329'
839
-
840
- res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6'
841
- res.body.should.equal '1.2.3.4'
842
- end
843
-
844
- should 'deals with proxies' do
845
- mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
846
-
847
- res = mock.get '/',
848
- 'REMOTE_ADDR' => '1.2.3.4',
849
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
850
- res.body.should.equal '1.2.3.4'
851
-
852
- res = mock.get '/',
853
- 'REMOTE_ADDR' => '127.0.0.1',
854
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
855
- res.body.should.equal '3.4.5.6'
856
-
857
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,3.4.5.6'
858
- res.body.should.equal '3.4.5.6'
859
-
860
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6'
861
- res.body.should.equal '3.4.5.6'
862
-
863
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6'
864
- res.body.should.equal '3.4.5.6'
865
-
866
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 10.0.0.1, 3.4.5.6'
867
- res.body.should.equal '3.4.5.6'
868
-
869
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '127.0.0.1, 3.4.5.6'
870
- res.body.should.equal '3.4.5.6'
871
-
872
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1'
873
- res.body.should.equal 'unknown'
874
-
875
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'other,unknown,192.168.0.1'
876
- res.body.should.equal 'unknown'
877
-
878
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,localhost,192.168.0.1'
879
- res.body.should.equal 'unknown'
880
-
881
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4'
882
- res.body.should.equal '3.4.5.6'
883
-
884
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '::1,2620:0:1c00:0:812c:9583:754b:ca11'
885
- res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11'
886
-
887
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '2620:0:1c00:0:812c:9583:754b:ca11,::1'
888
- res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11'
889
-
890
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'fd5b:982e:9130:247f:0000:0000:0000:0000,2620:0:1c00:0:812c:9583:754b:ca11'
891
- res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11'
892
-
893
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '2620:0:1c00:0:812c:9583:754b:ca11,fd5b:982e:9130:247f:0000:0000:0000:0000'
894
- res.body.should.equal '2620:0:1c00:0:812c:9583:754b:ca11'
895
-
896
- res = mock.get '/',
897
- 'HTTP_X_FORWARDED_FOR' => '1.1.1.1, 127.0.0.1',
898
- 'HTTP_CLIENT_IP' => '1.1.1.1'
899
- res.body.should.equal '1.1.1.1'
900
-
901
- # Spoofing attempt
902
- res = mock.get '/',
903
- 'HTTP_X_FORWARDED_FOR' => '1.1.1.1',
904
- 'HTTP_CLIENT_IP' => '2.2.2.2'
905
- res.body.should.equal '1.1.1.1'
906
-
907
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, 9.9.9.9'
908
- res.body.should.equal '9.9.9.9'
909
-
910
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, fe80::202:b3ff:fe1e:8329'
911
- res.body.should.equal 'fe80::202:b3ff:fe1e:8329'
912
- end
913
-
914
- class MyRequest < Rack::Request
915
- def params
916
- {:foo => "bar"}
917
- end
918
- end
919
-
920
- should "allow subclass request to be instantiated after parent request" do
921
- env = Rack::MockRequest.env_for("/?foo=bar")
922
-
923
- req1 = Rack::Request.new(env)
924
- req1.GET.should.equal "foo" => "bar"
925
- req1.params.should.equal "foo" => "bar"
926
-
927
- req2 = MyRequest.new(env)
928
- req2.GET.should.equal "foo" => "bar"
929
- req2.params.should.equal :foo => "bar"
930
- end
931
-
932
- should "allow parent request to be instantiated after subclass request" do
933
- env = Rack::MockRequest.env_for("/?foo=bar")
934
-
935
- req1 = MyRequest.new(env)
936
- req1.GET.should.equal "foo" => "bar"
937
- req1.params.should.equal :foo => "bar"
938
-
939
- req2 = Rack::Request.new(env)
940
- req2.GET.should.equal "foo" => "bar"
941
- req2.params.should.equal "foo" => "bar"
942
- end
943
-
944
- (0x20...0x7E).collect { |a|
945
- b = a.chr
946
- c = CGI.escape(b)
947
- should "not strip '#{a}' => '#{c}' => '#{b}' escaped character from parameters when accessed as string" do
948
- url = "/?foo=#{c}bar#{c}"
949
- env = Rack::MockRequest.env_for(url)
950
- req2 = Rack::Request.new(env)
951
- req2.GET.should.equal "foo" => "#{b}bar#{b}"
952
- req2.params.should.equal "foo" => "#{b}bar#{b}"
953
- end
954
- }
955
- end