rack 2.0.8 → 2.1.2

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 (188) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +69 -0
  3. data/{COPYING → MIT-LICENSE} +4 -2
  4. data/README.rdoc +77 -117
  5. data/Rakefile +25 -18
  6. data/SPEC +3 -4
  7. data/bin/rackup +1 -0
  8. data/example/lobster.ru +2 -0
  9. data/example/protectedlobster.rb +3 -1
  10. data/example/protectedlobster.ru +2 -0
  11. data/lib/rack.rb +63 -60
  12. data/lib/rack/auth/abstract/handler.rb +3 -1
  13. data/lib/rack/auth/abstract/request.rb +2 -0
  14. data/lib/rack/auth/basic.rb +4 -1
  15. data/lib/rack/auth/digest/md5.rb +9 -7
  16. data/lib/rack/auth/digest/nonce.rb +6 -3
  17. data/lib/rack/auth/digest/params.rb +4 -2
  18. data/lib/rack/auth/digest/request.rb +2 -0
  19. data/lib/rack/body_proxy.rb +3 -6
  20. data/lib/rack/builder.rb +39 -15
  21. data/lib/rack/cascade.rb +6 -5
  22. data/lib/rack/chunked.rb +29 -6
  23. data/lib/rack/common_logger.rb +9 -8
  24. data/lib/rack/conditional_get.rb +3 -1
  25. data/lib/rack/config.rb +2 -0
  26. data/lib/rack/content_length.rb +3 -1
  27. data/lib/rack/content_type.rb +3 -1
  28. data/lib/rack/core_ext/regexp.rb +14 -0
  29. data/lib/rack/deflater.rb +32 -17
  30. data/lib/rack/directory.rb +17 -14
  31. data/lib/rack/etag.rb +3 -1
  32. data/lib/rack/events.rb +5 -3
  33. data/lib/rack/file.rb +4 -173
  34. data/lib/rack/files.rb +178 -0
  35. data/lib/rack/handler.rb +7 -2
  36. data/lib/rack/handler/cgi.rb +3 -1
  37. data/lib/rack/handler/fastcgi.rb +4 -2
  38. data/lib/rack/handler/lsws.rb +3 -1
  39. data/lib/rack/handler/scgi.rb +9 -6
  40. data/lib/rack/handler/thin.rb +3 -1
  41. data/lib/rack/handler/webrick.rb +4 -2
  42. data/lib/rack/head.rb +2 -0
  43. data/lib/rack/lint.rb +14 -11
  44. data/lib/rack/lobster.rb +7 -5
  45. data/lib/rack/lock.rb +2 -0
  46. data/lib/rack/logger.rb +2 -0
  47. data/lib/rack/media_type.rb +10 -5
  48. data/lib/rack/method_override.rb +4 -2
  49. data/lib/rack/mime.rb +9 -1
  50. data/lib/rack/mock.rb +74 -15
  51. data/lib/rack/multipart.rb +5 -3
  52. data/lib/rack/multipart/generator.rb +6 -7
  53. data/lib/rack/multipart/parser.rb +51 -45
  54. data/lib/rack/multipart/uploaded_file.rb +2 -0
  55. data/lib/rack/null_logger.rb +2 -0
  56. data/lib/rack/query_parser.rb +51 -25
  57. data/lib/rack/recursive.rb +7 -5
  58. data/lib/rack/reloader.rb +10 -4
  59. data/lib/rack/request.rb +79 -26
  60. data/lib/rack/response.rb +71 -31
  61. data/lib/rack/rewindable_input.rb +4 -2
  62. data/lib/rack/runtime.rb +4 -2
  63. data/lib/rack/sendfile.rb +15 -8
  64. data/lib/rack/server.rb +88 -18
  65. data/lib/rack/session/abstract/id.rb +32 -22
  66. data/lib/rack/session/cookie.rb +10 -9
  67. data/lib/rack/session/memcache.rb +4 -93
  68. data/lib/rack/session/pool.rb +4 -2
  69. data/lib/rack/show_exceptions.rb +15 -9
  70. data/lib/rack/show_status.rb +4 -2
  71. data/lib/rack/static.rb +15 -10
  72. data/lib/rack/tempfile_reaper.rb +2 -0
  73. data/lib/rack/urlmap.rb +11 -2
  74. data/lib/rack/utils.rb +55 -70
  75. data/rack.gemspec +17 -7
  76. metadata +29 -169
  77. data/HISTORY.md +0 -505
  78. data/test/builder/an_underscore_app.rb +0 -5
  79. data/test/builder/anything.rb +0 -5
  80. data/test/builder/comment.ru +0 -4
  81. data/test/builder/end.ru +0 -5
  82. data/test/builder/line.ru +0 -1
  83. data/test/builder/options.ru +0 -2
  84. data/test/cgi/assets/folder/test.js +0 -1
  85. data/test/cgi/assets/fonts/font.eot +0 -1
  86. data/test/cgi/assets/images/image.png +0 -1
  87. data/test/cgi/assets/index.html +0 -1
  88. data/test/cgi/assets/javascripts/app.js +0 -1
  89. data/test/cgi/assets/stylesheets/app.css +0 -1
  90. data/test/cgi/lighttpd.conf +0 -26
  91. data/test/cgi/rackup_stub.rb +0 -6
  92. data/test/cgi/sample_rackup.ru +0 -5
  93. data/test/cgi/test +0 -9
  94. data/test/cgi/test+directory/test+file +0 -1
  95. data/test/cgi/test.fcgi +0 -9
  96. data/test/cgi/test.gz +0 -0
  97. data/test/cgi/test.ru +0 -5
  98. data/test/gemloader.rb +0 -10
  99. data/test/helper.rb +0 -34
  100. data/test/multipart/bad_robots +0 -259
  101. data/test/multipart/binary +0 -0
  102. data/test/multipart/content_type_and_no_filename +0 -6
  103. data/test/multipart/empty +0 -10
  104. data/test/multipart/fail_16384_nofile +0 -814
  105. data/test/multipart/file1.txt +0 -1
  106. data/test/multipart/filename_and_modification_param +0 -7
  107. data/test/multipart/filename_and_no_name +0 -6
  108. data/test/multipart/filename_with_encoded_words +0 -7
  109. data/test/multipart/filename_with_escaped_quotes +0 -6
  110. data/test/multipart/filename_with_escaped_quotes_and_modification_param +0 -7
  111. data/test/multipart/filename_with_null_byte +0 -7
  112. data/test/multipart/filename_with_percent_escaped_quotes +0 -6
  113. data/test/multipart/filename_with_single_quote +0 -7
  114. data/test/multipart/filename_with_unescaped_percentages +0 -6
  115. data/test/multipart/filename_with_unescaped_percentages2 +0 -6
  116. data/test/multipart/filename_with_unescaped_percentages3 +0 -6
  117. data/test/multipart/filename_with_unescaped_quotes +0 -6
  118. data/test/multipart/ie +0 -6
  119. data/test/multipart/invalid_character +0 -6
  120. data/test/multipart/mixed_files +0 -21
  121. data/test/multipart/nested +0 -10
  122. data/test/multipart/none +0 -9
  123. data/test/multipart/quoted +0 -15
  124. data/test/multipart/rack-logo.png +0 -0
  125. data/test/multipart/semicolon +0 -6
  126. data/test/multipart/text +0 -15
  127. data/test/multipart/three_files_three_fields +0 -31
  128. data/test/multipart/unity3d_wwwform +0 -11
  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_basic.rb +0 -89
  133. data/test/spec_auth_digest.rb +0 -260
  134. data/test/spec_body_proxy.rb +0 -85
  135. data/test/spec_builder.rb +0 -233
  136. data/test/spec_cascade.rb +0 -63
  137. data/test/spec_cgi.rb +0 -84
  138. data/test/spec_chunked.rb +0 -103
  139. data/test/spec_common_logger.rb +0 -95
  140. data/test/spec_conditional_get.rb +0 -103
  141. data/test/spec_config.rb +0 -23
  142. data/test/spec_content_length.rb +0 -86
  143. data/test/spec_content_type.rb +0 -46
  144. data/test/spec_deflater.rb +0 -375
  145. data/test/spec_directory.rb +0 -148
  146. data/test/spec_etag.rb +0 -108
  147. data/test/spec_events.rb +0 -133
  148. data/test/spec_fastcgi.rb +0 -85
  149. data/test/spec_file.rb +0 -264
  150. data/test/spec_handler.rb +0 -57
  151. data/test/spec_head.rb +0 -46
  152. data/test/spec_lint.rb +0 -515
  153. data/test/spec_lobster.rb +0 -59
  154. data/test/spec_lock.rb +0 -204
  155. data/test/spec_logger.rb +0 -24
  156. data/test/spec_media_type.rb +0 -42
  157. data/test/spec_method_override.rb +0 -110
  158. data/test/spec_mime.rb +0 -51
  159. data/test/spec_mock.rb +0 -359
  160. data/test/spec_multipart.rb +0 -722
  161. data/test/spec_null_logger.rb +0 -21
  162. data/test/spec_recursive.rb +0 -75
  163. data/test/spec_request.rb +0 -1407
  164. data/test/spec_response.rb +0 -510
  165. data/test/spec_rewindable_input.rb +0 -128
  166. data/test/spec_runtime.rb +0 -50
  167. data/test/spec_sendfile.rb +0 -125
  168. data/test/spec_server.rb +0 -193
  169. data/test/spec_session_abstract_id.rb +0 -31
  170. data/test/spec_session_abstract_session_hash.rb +0 -45
  171. data/test/spec_session_cookie.rb +0 -442
  172. data/test/spec_session_memcache.rb +0 -357
  173. data/test/spec_session_pool.rb +0 -247
  174. data/test/spec_show_exceptions.rb +0 -93
  175. data/test/spec_show_status.rb +0 -104
  176. data/test/spec_static.rb +0 -184
  177. data/test/spec_tempfile_reaper.rb +0 -64
  178. data/test/spec_thin.rb +0 -96
  179. data/test/spec_urlmap.rb +0 -237
  180. data/test/spec_utils.rb +0 -742
  181. data/test/spec_version.rb +0 -11
  182. data/test/spec_webrick.rb +0 -206
  183. data/test/static/another/index.html +0 -1
  184. data/test/static/foo.html +0 -1
  185. data/test/static/index.html +0 -1
  186. data/test/testrequest.rb +0 -78
  187. data/test/unregistered_handler/rack/handler/unregistered.rb +0 -7
  188. data/test/unregistered_handler/rack/handler/unregistered_long_one.rb +0 -7
@@ -1,21 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/lint'
3
- require 'rack/mock'
4
- require 'rack/null_logger'
5
-
6
- describe Rack::NullLogger do
7
- it "act as a noop logger" do
8
- app = lambda { |env|
9
- env['rack.logger'].warn "b00m"
10
- [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
11
- }
12
-
13
- logger = Rack::Lint.new(Rack::NullLogger.new(app))
14
-
15
- res = logger.call(Rack::MockRequest.env_for)
16
- res[0..1].must_equal [
17
- 200, {'Content-Type' => 'text/plain'}
18
- ]
19
- res[2].to_enum.to_a.must_equal ["Hello, World!"]
20
- end
21
- end
@@ -1,75 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'rack/lint'
3
- require 'rack/recursive'
4
- require 'rack/mock'
5
-
6
- describe Rack::Recursive do
7
- before do
8
- @app1 = lambda { |env|
9
- res = Rack::Response.new
10
- res["X-Path-Info"] = env["PATH_INFO"]
11
- res["X-Query-String"] = env["QUERY_STRING"]
12
- res.finish do |inner_res|
13
- inner_res.write "App1"
14
- end
15
- }
16
-
17
- @app2 = lambda { |env|
18
- Rack::Response.new.finish do |res|
19
- res.write "App2"
20
- _, _, body = env['rack.recursive.include'].call(env, "/app1")
21
- body.each { |b|
22
- res.write b
23
- }
24
- end
25
- }
26
-
27
- @app3 = lambda { |env|
28
- raise Rack::ForwardRequest.new("/app1")
29
- }
30
-
31
- @app4 = lambda { |env|
32
- raise Rack::ForwardRequest.new("http://example.org/app1/quux?meh")
33
- }
34
- end
35
-
36
- def recursive(map)
37
- Rack::Lint.new Rack::Recursive.new(Rack::URLMap.new(map))
38
- end
39
-
40
- it "allow for subrequests" do
41
- res = Rack::MockRequest.new(recursive("/app1" => @app1,
42
- "/app2" => @app2)).
43
- get("/app2")
44
-
45
- res.must_be :ok?
46
- res.body.must_equal "App2App1"
47
- end
48
-
49
- it "raise error on requests not below the app" do
50
- app = Rack::URLMap.new("/app1" => @app1,
51
- "/app" => recursive("/1" => @app1,
52
- "/2" => @app2))
53
-
54
- lambda {
55
- Rack::MockRequest.new(app).get("/app/2")
56
- }.must_raise(ArgumentError).
57
- message.must_match(/can only include below/)
58
- end
59
-
60
- it "support forwarding" do
61
- app = recursive("/app1" => @app1,
62
- "/app3" => @app3,
63
- "/app4" => @app4)
64
-
65
- res = Rack::MockRequest.new(app).get("/app3")
66
- res.must_be :ok?
67
- res.body.must_equal "App1"
68
-
69
- res = Rack::MockRequest.new(app).get("/app4")
70
- res.must_be :ok?
71
- res.body.must_equal "App1"
72
- res["X-Path-Info"].must_equal "/quux"
73
- res["X-Query-String"].must_equal "meh"
74
- end
75
- end
@@ -1,1407 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'stringio'
3
- require 'cgi'
4
- require 'rack/request'
5
- require 'rack/mock'
6
- require 'rack/multipart'
7
- require 'securerandom'
8
-
9
- class RackRequestTest < Minitest::Spec
10
- it "copies the env when duping" do
11
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
12
- refute_same req.env, req.dup.env
13
- end
14
-
15
- it 'can check if something has been set' do
16
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
17
- refute req.has_header?("FOO")
18
- end
19
-
20
- it "can get a key from the env" do
21
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
22
- assert_equal "example.com", req.get_header("SERVER_NAME")
23
- end
24
-
25
- it 'can calculate the authority' do
26
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
27
- assert_equal "example.com:8080", req.authority
28
- end
29
-
30
- it 'can calculate the authority without a port' do
31
- req = make_request(Rack::MockRequest.env_for("http://example.com/"))
32
- assert_equal "example.com:80", req.authority
33
- end
34
-
35
- it 'can calculate the authority without a port on ssl' do
36
- req = make_request(Rack::MockRequest.env_for("https://example.com/"))
37
- assert_equal "example.com:443", req.authority
38
- end
39
-
40
- it 'yields to the block if no value has been set' do
41
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
42
- yielded = false
43
- req.fetch_header("FOO") do
44
- yielded = true
45
- req.set_header "FOO", 'bar'
46
- end
47
-
48
- assert yielded
49
- assert_equal "bar", req.get_header("FOO")
50
- end
51
-
52
- it 'can iterate over values' do
53
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
54
- req.set_header 'foo', 'bar'
55
- hash = {}
56
- req.each_header do |k,v|
57
- hash[k] = v
58
- end
59
- assert_equal 'bar', hash['foo']
60
- end
61
-
62
- it 'can set values in the env' do
63
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
64
- req.set_header("FOO", "BAR")
65
- assert_equal "BAR", req.get_header("FOO")
66
- end
67
-
68
- it 'can add to multivalued headers in the env' do
69
- req = make_request(Rack::MockRequest.env_for('http://example.com:8080/'))
70
-
71
- assert_equal '1', req.add_header('FOO', '1')
72
- assert_equal '1', req.get_header('FOO')
73
-
74
- assert_equal '1,2', req.add_header('FOO', '2')
75
- assert_equal '1,2', req.get_header('FOO')
76
-
77
- assert_equal '1,2', req.add_header('FOO', nil)
78
- assert_equal '1,2', req.get_header('FOO')
79
- end
80
-
81
- it 'can delete env values' do
82
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
83
- req.set_header 'foo', 'bar'
84
- assert req.has_header? 'foo'
85
- req.delete_header 'foo'
86
- refute req.has_header? 'foo'
87
- end
88
-
89
- it "wrap the rack variables" do
90
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
91
-
92
- req.body.must_respond_to :gets
93
- req.scheme.must_equal "http"
94
- req.request_method.must_equal "GET"
95
-
96
- req.must_be :get?
97
- req.wont_be :post?
98
- req.wont_be :put?
99
- req.wont_be :delete?
100
- req.wont_be :head?
101
- req.wont_be :patch?
102
-
103
- req.script_name.must_equal ""
104
- req.path_info.must_equal "/"
105
- req.query_string.must_equal ""
106
-
107
- req.host.must_equal "example.com"
108
- req.port.must_equal 8080
109
-
110
- req.content_length.must_equal "0"
111
- req.content_type.must_be_nil
112
- end
113
-
114
- it "figure out the correct host" do
115
- req = make_request \
116
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
117
- req.host.must_equal "www2.example.org"
118
-
119
- req = make_request \
120
- Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
121
- req.host.must_equal "example.org"
122
-
123
- req = make_request \
124
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
125
- req.host.must_equal "example.org"
126
-
127
- env = Rack::MockRequest.env_for("/", "SERVER_ADDR" => "192.168.1.1", "SERVER_PORT" => "9292")
128
- env.delete("SERVER_NAME")
129
- req = make_request(env)
130
- req.host.must_equal "192.168.1.1"
131
-
132
- env = Rack::MockRequest.env_for("/")
133
- env.delete("SERVER_NAME")
134
- req = make_request(env)
135
- req.host.must_equal ""
136
- end
137
-
138
- it "figure out the correct port" do
139
- req = make_request \
140
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
141
- req.port.must_equal 80
142
-
143
- req = make_request \
144
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org:81")
145
- req.port.must_equal 81
146
-
147
- req = make_request \
148
- Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
149
- req.port.must_equal 9292
150
-
151
- req = make_request \
152
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
153
- req.port.must_equal 9292
154
-
155
- req = make_request \
156
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org")
157
- req.port.must_equal 80
158
-
159
- req = make_request \
160
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_SSL" => "on")
161
- req.port.must_equal 443
162
-
163
- req = make_request \
164
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PROTO" => "https")
165
- req.port.must_equal 443
166
-
167
- req = make_request \
168
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "HTTP_X_FORWARDED_PORT" => "9393")
169
- req.port.must_equal 9393
170
-
171
- req = make_request \
172
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9393", "SERVER_PORT" => "80")
173
- req.port.must_equal 9393
174
-
175
- req = make_request \
176
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393")
177
- req.port.must_equal 80
178
-
179
- req = make_request \
180
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost", "HTTP_X_FORWARDED_PROTO" => "https", "SERVER_PORT" => "80")
181
- req.port.must_equal 443
182
-
183
- req = make_request \
184
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost", "HTTP_X_FORWARDED_PROTO" => "https,https", "SERVER_PORT" => "80")
185
- req.port.must_equal 443
186
- end
187
-
188
- it "figure out the correct host with port" do
189
- req = make_request \
190
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
191
- req.host_with_port.must_equal "www2.example.org"
192
-
193
- req = make_request \
194
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81")
195
- req.host_with_port.must_equal "localhost:81"
196
-
197
- req = make_request \
198
- Rack::MockRequest.env_for("/", "SERVER_NAME" => "example.org", "SERVER_PORT" => "9292")
199
- req.host_with_port.must_equal "example.org:9292"
200
-
201
- req = make_request \
202
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org:9292")
203
- req.host_with_port.must_equal "example.org:9292"
204
-
205
- req = make_request \
206
- Rack::MockRequest.env_for("/", "HTTP_HOST" => "localhost:81", "HTTP_X_FORWARDED_HOST" => "example.org", "SERVER_PORT" => "9393")
207
- req.host_with_port.must_equal "example.org"
208
- end
209
-
210
- it "parse the query string" do
211
- req = make_request(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
212
- req.query_string.must_equal "foo=bar&quux=bla"
213
- req.GET.must_equal "foo" => "bar", "quux" => "bla"
214
- req.POST.must_be :empty?
215
- req.params.must_equal "foo" => "bar", "quux" => "bla"
216
- end
217
-
218
- it "not truncate query strings containing semi-colons #543 only in POST" do
219
- mr = Rack::MockRequest.env_for("/",
220
- "REQUEST_METHOD" => 'POST',
221
- :input => "foo=bar&quux=b;la")
222
- req = make_request mr
223
- req.query_string.must_equal ""
224
- req.GET.must_be :empty?
225
- req.POST.must_equal "foo" => "bar", "quux" => "b;la"
226
- req.params.must_equal req.GET.merge(req.POST)
227
- end
228
-
229
- it "should use the query_parser for query parsing" do
230
- c = Class.new(Rack::QueryParser::Params) do
231
- def initialize(*)
232
- super
233
- @params = Hash.new{|h,k| h[k.to_s] if k.is_a?(Symbol)}
234
- end
235
- end
236
- parser = Rack::QueryParser.new(c, 65536, 100)
237
- c = Class.new(Rack::Request) do
238
- define_method(:query_parser) do
239
- parser
240
- end
241
- end
242
- req = c.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
243
- req.GET[:foo].must_equal "bar"
244
- req.GET[:quux].must_equal "bla"
245
- req.params[:foo].must_equal "bar"
246
- req.params[:quux].must_equal "bla"
247
- end
248
-
249
- it "use semi-colons as separators for query strings in GET" do
250
- req = make_request(Rack::MockRequest.env_for("/?foo=bar&quux=b;la;wun=duh"))
251
- req.query_string.must_equal "foo=bar&quux=b;la;wun=duh"
252
- req.GET.must_equal "foo" => "bar", "quux" => "b", "la" => nil, "wun" => "duh"
253
- req.POST.must_be :empty?
254
- req.params.must_equal "foo" => "bar", "quux" => "b", "la" => nil, "wun" => "duh"
255
- end
256
-
257
- it "limit the keys from the GET query string" do
258
- env = Rack::MockRequest.env_for("/?foo=bar")
259
-
260
- old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
261
- begin
262
- req = make_request(env)
263
- lambda { req.GET }.must_raise RangeError
264
- ensure
265
- Rack::Utils.key_space_limit = old
266
- end
267
- end
268
-
269
- it "limit the key size per nested params hash" do
270
- nested_query = Rack::MockRequest.env_for("/?foo%5Bbar%5D%5Bbaz%5D%5Bqux%5D=1")
271
- plain_query = Rack::MockRequest.env_for("/?foo_bar__baz__qux_=1")
272
-
273
- old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 3
274
- begin
275
- exp = {"foo"=>{"bar"=>{"baz"=>{"qux"=>"1"}}}}
276
- make_request(nested_query).GET.must_equal exp
277
- lambda { make_request(plain_query).GET }.must_raise RangeError
278
- ensure
279
- Rack::Utils.key_space_limit = old
280
- end
281
- end
282
-
283
- it "not unify GET and POST when calling params" do
284
- mr = Rack::MockRequest.env_for("/?foo=quux",
285
- "REQUEST_METHOD" => 'POST',
286
- :input => "foo=bar&quux=bla"
287
- )
288
- req = make_request mr
289
-
290
- req.params
291
-
292
- req.GET.must_equal "foo" => "quux"
293
- req.POST.must_equal "foo" => "bar", "quux" => "bla"
294
- req.params.must_equal req.GET.merge(req.POST)
295
- end
296
-
297
- it "use the query_parser's params_class for multipart params" do
298
- c = Class.new(Rack::QueryParser::Params) do
299
- def initialize(*)
300
- super
301
- @params = Hash.new{|h,k| h[k.to_s] if k.is_a?(Symbol)}
302
- end
303
- end
304
- parser = Rack::QueryParser.new(c, 65536, 100)
305
- c = Class.new(Rack::Request) do
306
- define_method(:query_parser) do
307
- parser
308
- end
309
- end
310
- mr = Rack::MockRequest.env_for("/?foo=quux",
311
- "REQUEST_METHOD" => 'POST',
312
- :input => "foo=bar&quux=bla"
313
- )
314
- req = c.new mr
315
-
316
- req.params
317
-
318
- req.GET[:foo].must_equal "quux"
319
- req.POST[:foo].must_equal "bar"
320
- req.POST[:quux].must_equal "bla"
321
- req.params[:foo].must_equal "bar"
322
- req.params[:quux].must_equal "bla"
323
- end
324
-
325
- it "raise if input params has invalid %-encoding" do
326
- mr = Rack::MockRequest.env_for("/?foo=quux",
327
- "REQUEST_METHOD" => 'POST',
328
- :input => "a%=1"
329
- )
330
- req = make_request mr
331
-
332
- lambda { req.POST }.must_raise(Rack::Utils::InvalidParameterError).
333
- message.must_equal "invalid %-encoding (a%)"
334
- end
335
-
336
- it "raise if rack.input is missing" do
337
- req = make_request({})
338
- lambda { req.POST }.must_raise RuntimeError
339
- end
340
-
341
- it "parse POST data when method is POST and no Content-Type given" do
342
- req = make_request \
343
- Rack::MockRequest.env_for("/?foo=quux",
344
- "REQUEST_METHOD" => 'POST',
345
- :input => "foo=bar&quux=bla")
346
- req.content_type.must_be_nil
347
- req.media_type.must_be_nil
348
- req.query_string.must_equal "foo=quux"
349
- req.GET.must_equal "foo" => "quux"
350
- req.POST.must_equal "foo" => "bar", "quux" => "bla"
351
- req.params.must_equal "foo" => "bar", "quux" => "bla"
352
- end
353
-
354
- it "limit the keys from the POST form data" do
355
- env = Rack::MockRequest.env_for("",
356
- "REQUEST_METHOD" => 'POST',
357
- :input => "foo=bar&quux=bla")
358
-
359
- old, Rack::Utils.key_space_limit = Rack::Utils.key_space_limit, 1
360
- begin
361
- req = make_request(env)
362
- lambda { req.POST }.must_raise RangeError
363
- ensure
364
- Rack::Utils.key_space_limit = old
365
- end
366
- end
367
-
368
- it "parse POST data with explicit content type regardless of method" do
369
- req = make_request \
370
- Rack::MockRequest.env_for("/",
371
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
372
- :input => "foo=bar&quux=bla")
373
- req.content_type.must_equal 'application/x-www-form-urlencoded;foo=bar'
374
- req.media_type.must_equal 'application/x-www-form-urlencoded'
375
- req.media_type_params['foo'].must_equal 'bar'
376
- req.POST.must_equal "foo" => "bar", "quux" => "bla"
377
- req.params.must_equal "foo" => "bar", "quux" => "bla"
378
- end
379
-
380
- it "not parse POST data when media type is not form-data" do
381
- req = make_request \
382
- Rack::MockRequest.env_for("/?foo=quux",
383
- "REQUEST_METHOD" => 'POST',
384
- "CONTENT_TYPE" => 'text/plain;charset=utf-8',
385
- :input => "foo=bar&quux=bla")
386
- req.content_type.must_equal 'text/plain;charset=utf-8'
387
- req.media_type.must_equal 'text/plain'
388
- req.media_type_params['charset'].must_equal 'utf-8'
389
- req.POST.must_be :empty?
390
- req.params.must_equal "foo" => "quux"
391
- req.body.read.must_equal "foo=bar&quux=bla"
392
- end
393
-
394
- it "parse POST data on PUT when media type is form-data" do
395
- req = make_request \
396
- Rack::MockRequest.env_for("/?foo=quux",
397
- "REQUEST_METHOD" => 'PUT',
398
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded',
399
- :input => "foo=bar&quux=bla")
400
- req.POST.must_equal "foo" => "bar", "quux" => "bla"
401
- req.body.read.must_equal "foo=bar&quux=bla"
402
- end
403
-
404
- it "rewind input after parsing POST data" do
405
- input = StringIO.new("foo=bar&quux=bla")
406
- req = make_request \
407
- Rack::MockRequest.env_for("/",
408
- "CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
409
- :input => input)
410
- req.params.must_equal "foo" => "bar", "quux" => "bla"
411
- input.read.must_equal "foo=bar&quux=bla"
412
- end
413
-
414
- it "safely accepts POST requests with empty body" do
415
- mr = Rack::MockRequest.env_for("/",
416
- "REQUEST_METHOD" => "POST",
417
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
418
- "CONTENT_LENGTH" => '0',
419
- :input => nil)
420
-
421
- req = make_request mr
422
- req.query_string.must_equal ""
423
- req.GET.must_be :empty?
424
- req.POST.must_be :empty?
425
- req.params.must_equal({})
426
- end
427
-
428
- it "clean up Safari's ajax POST body" do
429
- req = make_request \
430
- Rack::MockRequest.env_for("/",
431
- 'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0")
432
- req.POST.must_equal "foo" => "bar", "quux" => "bla"
433
- end
434
-
435
- it "get value by key from params with #[]" do
436
- req = make_request \
437
- Rack::MockRequest.env_for("?foo=quux")
438
- req['foo'].must_equal 'quux'
439
- req[:foo].must_equal 'quux'
440
- end
441
-
442
- it "set value to key on params with #[]=" do
443
- req = make_request \
444
- Rack::MockRequest.env_for("?foo=duh")
445
- req['foo'].must_equal 'duh'
446
- req[:foo].must_equal 'duh'
447
- req.params.must_equal 'foo' => 'duh'
448
-
449
- if req.delegate?
450
- skip "delegate requests don't cache params, so mutations have no impact"
451
- end
452
-
453
- req['foo'] = 'bar'
454
- req.params.must_equal 'foo' => 'bar'
455
- req['foo'].must_equal 'bar'
456
- req[:foo].must_equal 'bar'
457
-
458
- req[:foo] = 'jaz'
459
- req.params.must_equal 'foo' => 'jaz'
460
- req['foo'].must_equal 'jaz'
461
- req[:foo].must_equal 'jaz'
462
- end
463
-
464
- it "return values for the keys in the order given from values_at" do
465
- req = make_request \
466
- Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful")
467
- req.values_at('foo').must_equal ['baz']
468
- req.values_at('foo', 'wun').must_equal ['baz', 'der']
469
- req.values_at('bar', 'foo', 'wun').must_equal ['ful', 'baz', 'der']
470
- end
471
-
472
- it "extract referrer correctly" do
473
- req = make_request \
474
- Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path")
475
- req.referer.must_equal "/some/path"
476
-
477
- req = make_request \
478
- Rack::MockRequest.env_for("/")
479
- req.referer.must_be_nil
480
- end
481
-
482
- it "extract user agent correctly" do
483
- req = make_request \
484
- Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)")
485
- req.user_agent.must_equal "Mozilla/4.0 (compatible)"
486
-
487
- req = make_request \
488
- Rack::MockRequest.env_for("/")
489
- req.user_agent.must_be_nil
490
- end
491
-
492
- it "treat missing content type as nil" do
493
- req = make_request \
494
- Rack::MockRequest.env_for("/")
495
- req.content_type.must_be_nil
496
- end
497
-
498
- it "treat empty content type as nil" do
499
- req = make_request \
500
- Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
501
- req.content_type.must_be_nil
502
- end
503
-
504
- it "return nil media type for empty content type" do
505
- req = make_request \
506
- Rack::MockRequest.env_for("/", "CONTENT_TYPE" => "")
507
- req.media_type.must_be_nil
508
- end
509
-
510
- it "cache, but invalidates the cache" do
511
- req = make_request \
512
- Rack::MockRequest.env_for("/?foo=quux",
513
- "CONTENT_TYPE" => "application/x-www-form-urlencoded",
514
- :input => "foo=bar&quux=bla")
515
- req.GET.must_equal "foo" => "quux"
516
- req.GET.must_equal "foo" => "quux"
517
- req.set_header("QUERY_STRING", "bla=foo")
518
- req.GET.must_equal "bla" => "foo"
519
- req.GET.must_equal "bla" => "foo"
520
-
521
- req.POST.must_equal "foo" => "bar", "quux" => "bla"
522
- req.POST.must_equal "foo" => "bar", "quux" => "bla"
523
- req.set_header("rack.input", StringIO.new("foo=bla&quux=bar"))
524
- req.POST.must_equal "foo" => "bla", "quux" => "bar"
525
- req.POST.must_equal "foo" => "bla", "quux" => "bar"
526
- end
527
-
528
- it "figure out if called via XHR" do
529
- req = make_request(Rack::MockRequest.env_for(""))
530
- req.wont_be :xhr?
531
-
532
- req = make_request \
533
- Rack::MockRequest.env_for("", "HTTP_X_REQUESTED_WITH" => "XMLHttpRequest")
534
- req.must_be :xhr?
535
- end
536
-
537
- it "ssl detection" do
538
- request = make_request(Rack::MockRequest.env_for("/"))
539
- request.scheme.must_equal "http"
540
- request.wont_be :ssl?
541
-
542
- request = make_request(Rack::MockRequest.env_for("/", 'HTTPS' => 'on'))
543
- request.scheme.must_equal "https"
544
- request.must_be :ssl?
545
-
546
- request = make_request(Rack::MockRequest.env_for("/", 'rack.url_scheme' => 'https'))
547
- request.scheme.must_equal "https"
548
- request.must_be :ssl?
549
-
550
- request = make_request(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8080'))
551
- request.scheme.must_equal "http"
552
- request.wont_be :ssl?
553
-
554
- request = make_request(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTPS' => 'on'))
555
- request.scheme.must_equal "https"
556
- request.must_be :ssl?
557
-
558
- request = make_request(Rack::MockRequest.env_for("/", 'HTTP_HOST' => 'www.example.org:8443', 'HTTP_X_FORWARDED_SSL' => 'on'))
559
- request.scheme.must_equal "https"
560
- request.must_be :ssl?
561
-
562
- request = make_request(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_SCHEME' => 'https'))
563
- request.scheme.must_equal "https"
564
- request.must_be :ssl?
565
-
566
- request = make_request(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https'))
567
- request.scheme.must_equal "https"
568
- request.must_be :ssl?
569
-
570
- request = make_request(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_PROTO' => 'https, http, http'))
571
- request.scheme.must_equal "https"
572
- request.must_be :ssl?
573
- end
574
-
575
- it "prevents scheme abuse" do
576
- request = make_request(Rack::MockRequest.env_for("/", 'HTTP_X_FORWARDED_SCHEME' => 'a."><script>alert(1)</script>'))
577
- request.scheme.must_equal 'http'
578
- end
579
-
580
- it "parse cookies" do
581
- req = make_request \
582
- Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
583
- req.cookies.must_equal "foo" => "bar", "quux" => "h&m"
584
- req.cookies.must_equal "foo" => "bar", "quux" => "h&m"
585
- req.delete_header("HTTP_COOKIE")
586
- req.cookies.must_equal({})
587
- end
588
-
589
- it "always return the same hash object" do
590
- req = make_request \
591
- Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
592
- hash = req.cookies
593
- req.env.delete("HTTP_COOKIE")
594
- req.cookies.must_equal hash
595
- req.env["HTTP_COOKIE"] = "zoo=m"
596
- req.cookies.must_equal hash
597
- end
598
-
599
- it "modify the cookies hash in place" do
600
- req = make_request(Rack::MockRequest.env_for(""))
601
- req.cookies.must_equal({})
602
- req.cookies['foo'] = 'bar'
603
- req.cookies.must_equal 'foo' => 'bar'
604
- end
605
-
606
- it "not modify the params hash in place" do
607
- e = Rack::MockRequest.env_for("")
608
- req1 = make_request(e)
609
- if req1.delegate?
610
- skip "delegate requests don't cache params, so mutations have no impact"
611
- end
612
- req1.params.must_equal({})
613
- req1.params['foo'] = 'bar'
614
- req1.params.must_equal 'foo' => 'bar'
615
- req2 = make_request(e)
616
- req2.params.must_equal({})
617
- end
618
-
619
- it "modify params hash if param is in GET" do
620
- e = Rack::MockRequest.env_for("?foo=duh")
621
- req1 = make_request(e)
622
- req1.params.must_equal 'foo' => 'duh'
623
- req1.update_param 'foo', 'bar'
624
- req1.params.must_equal 'foo' => 'bar'
625
- req2 = make_request(e)
626
- req2.params.must_equal 'foo' => 'bar'
627
- end
628
-
629
- it "modify params hash if param is in POST" do
630
- e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => 'foo=duh')
631
- req1 = make_request(e)
632
- req1.params.must_equal 'foo' => 'duh'
633
- req1.update_param 'foo', 'bar'
634
- req1.params.must_equal 'foo' => 'bar'
635
- req2 = make_request(e)
636
- req2.params.must_equal 'foo' => 'bar'
637
- end
638
-
639
- it "modify params hash, even if param didn't exist before" do
640
- e = Rack::MockRequest.env_for("")
641
- req1 = make_request(e)
642
- req1.params.must_equal({})
643
- req1.update_param 'foo', 'bar'
644
- req1.params.must_equal 'foo' => 'bar'
645
- req2 = make_request(e)
646
- req2.params.must_equal 'foo' => 'bar'
647
- end
648
-
649
- it "modify params hash by changing only GET" do
650
- e = Rack::MockRequest.env_for("?foo=duhget")
651
- req = make_request(e)
652
- req.GET.must_equal 'foo' => 'duhget'
653
- req.POST.must_equal({})
654
- req.update_param 'foo', 'bar'
655
- req.GET.must_equal 'foo' => 'bar'
656
- req.POST.must_equal({})
657
- end
658
-
659
- it "modify params hash by changing only POST" do
660
- e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => "foo=duhpost")
661
- req = make_request(e)
662
- req.GET.must_equal({})
663
- req.POST.must_equal 'foo' => 'duhpost'
664
- req.update_param 'foo', 'bar'
665
- req.GET.must_equal({})
666
- req.POST.must_equal 'foo' => 'bar'
667
- end
668
-
669
- it "modify params hash, even if param is defined in both POST and GET" do
670
- e = Rack::MockRequest.env_for("?foo=duhget", "REQUEST_METHOD" => 'POST', :input => "foo=duhpost")
671
- req1 = make_request(e)
672
- req1.GET.must_equal 'foo' => 'duhget'
673
- req1.POST.must_equal 'foo' => 'duhpost'
674
- req1.params.must_equal 'foo' => 'duhpost'
675
- req1.update_param 'foo', 'bar'
676
- req1.GET.must_equal 'foo' => 'bar'
677
- req1.POST.must_equal 'foo' => 'bar'
678
- req1.params.must_equal 'foo' => 'bar'
679
- req2 = make_request(e)
680
- req2.GET.must_equal 'foo' => 'bar'
681
- req2.POST.must_equal 'foo' => 'bar'
682
- req2.params.must_equal 'foo' => 'bar'
683
- req2.params.must_equal 'foo' => 'bar'
684
- end
685
-
686
- it "allow deleting from params hash if param is in GET" do
687
- e = Rack::MockRequest.env_for("?foo=bar")
688
- req1 = make_request(e)
689
- req1.params.must_equal 'foo' => 'bar'
690
- req1.delete_param('foo').must_equal 'bar'
691
- req1.params.must_equal({})
692
- req2 = make_request(e)
693
- req2.params.must_equal({})
694
- end
695
-
696
- it "allow deleting from params hash if param is in POST" do
697
- e = Rack::MockRequest.env_for("", "REQUEST_METHOD" => 'POST', :input => 'foo=bar')
698
- req1 = make_request(e)
699
- req1.params.must_equal 'foo' => 'bar'
700
- req1.delete_param('foo').must_equal 'bar'
701
- req1.params.must_equal({})
702
- req2 = make_request(e)
703
- req2.params.must_equal({})
704
- end
705
-
706
- it "pass through non-uri escaped cookies as-is" do
707
- req = make_request Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=%")
708
- req.cookies["foo"].must_equal "%"
709
- end
710
-
711
- it "parse cookies according to RFC 2109" do
712
- req = make_request \
713
- Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car')
714
- req.cookies.must_equal 'foo' => 'bar'
715
- end
716
-
717
- it 'parse cookies with quotes' do
718
- req = make_request Rack::MockRequest.env_for('', {
719
- 'HTTP_COOKIE' => '$Version="1"; Customer="WILE_E_COYOTE"; $Path="/acme"; Part_Number="Rocket_Launcher_0001"; $Path="/acme"'
720
- })
721
- req.cookies.must_equal({
722
- '$Version' => '"1"',
723
- 'Customer' => '"WILE_E_COYOTE"',
724
- '$Path' => '"/acme"',
725
- 'Part_Number' => '"Rocket_Launcher_0001"',
726
- })
727
- end
728
-
729
- it "provide setters" do
730
- req = make_request(e=Rack::MockRequest.env_for(""))
731
- req.script_name.must_equal ""
732
- req.script_name = "/foo"
733
- req.script_name.must_equal "/foo"
734
- e["SCRIPT_NAME"].must_equal "/foo"
735
-
736
- req.path_info.must_equal "/"
737
- req.path_info = "/foo"
738
- req.path_info.must_equal "/foo"
739
- e["PATH_INFO"].must_equal "/foo"
740
- end
741
-
742
- it "provide the original env" do
743
- req = make_request(e = Rack::MockRequest.env_for(""))
744
- req.env.must_equal e
745
- end
746
-
747
- it "restore the base URL" do
748
- make_request(Rack::MockRequest.env_for("")).base_url.
749
- must_equal "http://example.org"
750
- make_request(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).base_url.
751
- must_equal "http://example.org"
752
- end
753
-
754
- it "restore the URL" do
755
- make_request(Rack::MockRequest.env_for("")).url.
756
- must_equal "http://example.org/"
757
- make_request(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url.
758
- must_equal "http://example.org/foo/"
759
- make_request(Rack::MockRequest.env_for("/foo")).url.
760
- must_equal "http://example.org/foo"
761
- make_request(Rack::MockRequest.env_for("?foo")).url.
762
- must_equal "http://example.org/?foo"
763
- make_request(Rack::MockRequest.env_for("http://example.org:8080/")).url.
764
- must_equal "http://example.org:8080/"
765
- make_request(Rack::MockRequest.env_for("https://example.org/")).url.
766
- must_equal "https://example.org/"
767
- make_request(Rack::MockRequest.env_for("coffee://example.org/")).url.
768
- must_equal "coffee://example.org/"
769
- make_request(Rack::MockRequest.env_for("coffee://example.org:443/")).url.
770
- must_equal "coffee://example.org:443/"
771
- make_request(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).url.
772
- must_equal "https://example.com:8080/foo?foo"
773
- end
774
-
775
- it "restore the full path" do
776
- make_request(Rack::MockRequest.env_for("")).fullpath.
777
- must_equal "/"
778
- make_request(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath.
779
- must_equal "/foo/"
780
- make_request(Rack::MockRequest.env_for("/foo")).fullpath.
781
- must_equal "/foo"
782
- make_request(Rack::MockRequest.env_for("?foo")).fullpath.
783
- must_equal "/?foo"
784
- make_request(Rack::MockRequest.env_for("http://example.org:8080/")).fullpath.
785
- must_equal "/"
786
- make_request(Rack::MockRequest.env_for("https://example.org/")).fullpath.
787
- must_equal "/"
788
-
789
- make_request(Rack::MockRequest.env_for("https://example.com:8080/foo?foo")).fullpath.
790
- must_equal "/foo?foo"
791
- end
792
-
793
- it "handle multiple media type parameters" do
794
- req = make_request \
795
- Rack::MockRequest.env_for("/",
796
- "CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam;blong="boo";zump="zoo\"o";weird=lol"')
797
- req.wont_be :form_data?
798
- req.media_type_params.must_include 'foo'
799
- req.media_type_params['foo'].must_equal 'BAR'
800
- req.media_type_params.must_include 'baz'
801
- req.media_type_params['baz'].must_equal 'bizzle dizzle'
802
- req.media_type_params.wont_include 'BLING'
803
- req.media_type_params.must_include 'bling'
804
- req.media_type_params['bling'].must_equal 'bam'
805
- req.media_type_params['blong'].must_equal 'boo'
806
- req.media_type_params['zump'].must_equal 'zoo\"o'
807
- req.media_type_params['weird'].must_equal 'lol"'
808
- end
809
-
810
- it "parse with junk before boundary" do
811
- # Adapted from RFC 1867.
812
- input = <<EOF
813
- blah blah\r
814
- \r
815
- --AaB03x\r
816
- content-disposition: form-data; name="reply"\r
817
- \r
818
- yes\r
819
- --AaB03x\r
820
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
821
- Content-Type: image/jpeg\r
822
- Content-Transfer-Encoding: base64\r
823
- \r
824
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
825
- --AaB03x--\r
826
- EOF
827
- req = make_request Rack::MockRequest.env_for("/",
828
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
829
- "CONTENT_LENGTH" => input.size,
830
- :input => input)
831
-
832
- req.POST.must_include "fileupload"
833
- req.POST.must_include "reply"
834
-
835
- req.must_be :form_data?
836
- req.content_length.must_equal input.size
837
- req.media_type.must_equal 'multipart/form-data'
838
- req.media_type_params.must_include 'boundary'
839
- req.media_type_params['boundary'].must_equal 'AaB03x'
840
-
841
- req.POST["reply"].must_equal "yes"
842
-
843
- f = req.POST["fileupload"]
844
- f.must_be_kind_of Hash
845
- f[:type].must_equal "image/jpeg"
846
- f[:filename].must_equal "dj.jpg"
847
- f.must_include :tempfile
848
- f[:tempfile].size.must_equal 76
849
- end
850
-
851
- it "not infinite loop with a malformed HTTP request" do
852
- # Adapted from RFC 1867.
853
- input = <<EOF
854
- --AaB03x
855
- content-disposition: form-data; name="reply"
856
-
857
- yes
858
- --AaB03x
859
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"
860
- Content-Type: image/jpeg
861
- Content-Transfer-Encoding: base64
862
-
863
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg
864
- --AaB03x--
865
- EOF
866
- req = make_request Rack::MockRequest.env_for("/",
867
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
868
- "CONTENT_LENGTH" => input.size,
869
- :input => input)
870
-
871
- lambda{req.POST}.must_raise EOFError
872
- end
873
-
874
-
875
- it "parse multipart form data" do
876
- # Adapted from RFC 1867.
877
- input = <<EOF
878
- --AaB03x\r
879
- content-disposition: form-data; name="reply"\r
880
- \r
881
- yes\r
882
- --AaB03x\r
883
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
884
- Content-Type: image/jpeg\r
885
- Content-Transfer-Encoding: base64\r
886
- \r
887
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
888
- --AaB03x--\r
889
- EOF
890
- req = make_request Rack::MockRequest.env_for("/",
891
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
892
- "CONTENT_LENGTH" => input.size,
893
- :input => input)
894
-
895
- req.POST.must_include "fileupload"
896
- req.POST.must_include "reply"
897
-
898
- req.must_be :form_data?
899
- req.content_length.must_equal input.size
900
- req.media_type.must_equal 'multipart/form-data'
901
- req.media_type_params.must_include 'boundary'
902
- req.media_type_params['boundary'].must_equal 'AaB03x'
903
-
904
- req.POST["reply"].must_equal "yes"
905
-
906
- f = req.POST["fileupload"]
907
- f.must_be_kind_of Hash
908
- f[:type].must_equal "image/jpeg"
909
- f[:filename].must_equal "dj.jpg"
910
- f.must_include :tempfile
911
- f[:tempfile].size.must_equal 76
912
- end
913
-
914
- it "MultipartPartLimitError when request has too many multipart parts if limit set" do
915
- begin
916
- 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")
917
- data += "--AaB03x--\r"
918
-
919
- options = {
920
- "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
921
- "CONTENT_LENGTH" => data.length.to_s,
922
- :input => StringIO.new(data)
923
- }
924
-
925
- request = make_request Rack::MockRequest.env_for("/", options)
926
- lambda { request.POST }.must_raise Rack::Multipart::MultipartPartLimitError
927
- end
928
- end
929
-
930
- it 'closes tempfiles it created in the case of too many created' do
931
- begin
932
- 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")
933
- data += "--AaB03x--\r"
934
-
935
- files = []
936
- options = {
937
- "CONTENT_TYPE" => "multipart/form-data; boundary=AaB03x",
938
- "CONTENT_LENGTH" => data.length.to_s,
939
- Rack::RACK_MULTIPART_TEMPFILE_FACTORY => lambda { |filename, content_type|
940
- file = Tempfile.new(["RackMultipart", ::File.extname(filename)])
941
- files << file
942
- file
943
- },
944
- :input => StringIO.new(data)
945
- }
946
-
947
- request = make_request Rack::MockRequest.env_for("/", options)
948
- assert_raises(Rack::Multipart::MultipartPartLimitError) do
949
- request.POST
950
- end
951
- refute_predicate files, :empty?
952
- files.each { |f| assert_predicate f, :closed? }
953
- end
954
- end
955
-
956
- it "parse big multipart form data" do
957
- input = <<EOF
958
- --AaB03x\r
959
- content-disposition: form-data; name="huge"; filename="huge"\r
960
- \r
961
- #{"x"*32768}\r
962
- --AaB03x\r
963
- content-disposition: form-data; name="mean"; filename="mean"\r
964
- \r
965
- --AaB03xha\r
966
- --AaB03x--\r
967
- EOF
968
- req = make_request Rack::MockRequest.env_for("/",
969
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
970
- "CONTENT_LENGTH" => input.size,
971
- :input => input)
972
-
973
- req.POST["huge"][:tempfile].size.must_equal 32768
974
- req.POST["mean"][:tempfile].size.must_equal 10
975
- req.POST["mean"][:tempfile].read.must_equal "--AaB03xha"
976
- end
977
-
978
- it "record tempfiles from multipart form data in env[rack.tempfiles]" do
979
- input = <<EOF
980
- --AaB03x\r
981
- content-disposition: form-data; name="fileupload"; filename="foo.jpg"\r
982
- Content-Type: image/jpeg\r
983
- Content-Transfer-Encoding: base64\r
984
- \r
985
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
986
- --AaB03x\r
987
- content-disposition: form-data; name="fileupload"; filename="bar.jpg"\r
988
- Content-Type: image/jpeg\r
989
- Content-Transfer-Encoding: base64\r
990
- \r
991
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
992
- --AaB03x--\r
993
- EOF
994
- env = Rack::MockRequest.env_for("/",
995
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
996
- "CONTENT_LENGTH" => input.size,
997
- :input => input)
998
- req = make_request(env)
999
- req.params
1000
- env['rack.tempfiles'].size.must_equal 2
1001
- end
1002
-
1003
- it "detect invalid multipart form data" do
1004
- input = <<EOF
1005
- --AaB03x\r
1006
- content-disposition: form-data; name="huge"; filename="huge"\r
1007
- EOF
1008
- req = make_request Rack::MockRequest.env_for("/",
1009
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
1010
- "CONTENT_LENGTH" => input.size,
1011
- :input => input)
1012
-
1013
- lambda { req.POST }.must_raise EOFError
1014
-
1015
- input = <<EOF
1016
- --AaB03x\r
1017
- content-disposition: form-data; name="huge"; filename="huge"\r
1018
- \r
1019
- foo\r
1020
- EOF
1021
- req = make_request Rack::MockRequest.env_for("/",
1022
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
1023
- "CONTENT_LENGTH" => input.size,
1024
- :input => input)
1025
-
1026
- lambda { req.POST }.must_raise EOFError
1027
-
1028
- input = <<EOF
1029
- --AaB03x\r
1030
- content-disposition: form-data; name="huge"; filename="huge"\r
1031
- \r
1032
- foo\r
1033
- EOF
1034
- req = make_request Rack::MockRequest.env_for("/",
1035
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
1036
- "CONTENT_LENGTH" => input.size,
1037
- :input => input)
1038
-
1039
- lambda { req.POST }.must_raise EOFError
1040
- end
1041
-
1042
- it "consistently raise EOFError on bad multipart form data" do
1043
- input = <<EOF
1044
- --AaB03x\r
1045
- content-disposition: form-data; name="huge"; filename="huge"\r
1046
- EOF
1047
- req = make_request Rack::MockRequest.env_for("/",
1048
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
1049
- "CONTENT_LENGTH" => input.size,
1050
- :input => input)
1051
-
1052
- lambda { req.POST }.must_raise EOFError
1053
- lambda { req.POST }.must_raise EOFError
1054
- end
1055
-
1056
- it "correctly parse the part name from Content-Id header" do
1057
- input = <<EOF
1058
- --AaB03x\r
1059
- Content-Type: text/xml; charset=utf-8\r
1060
- Content-Id: <soap-start>\r
1061
- Content-Transfer-Encoding: 7bit\r
1062
- \r
1063
- foo\r
1064
- --AaB03x--\r
1065
- EOF
1066
- req = make_request Rack::MockRequest.env_for("/",
1067
- "CONTENT_TYPE" => "multipart/related, boundary=AaB03x",
1068
- "CONTENT_LENGTH" => input.size,
1069
- :input => input)
1070
-
1071
- req.params.keys.must_equal ["<soap-start>"]
1072
- end
1073
-
1074
- it "not try to interpret binary as utf8" do
1075
- input = <<EOF
1076
- --AaB03x\r
1077
- content-disposition: form-data; name="fileupload"; filename="junk.a"\r
1078
- content-type: application/octet-stream\r
1079
- \r
1080
- #{[0x36,0xCF,0x0A,0xF8].pack('c*')}\r
1081
- --AaB03x--\r
1082
- EOF
1083
-
1084
- req = make_request Rack::MockRequest.env_for("/",
1085
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
1086
- "CONTENT_LENGTH" => input.size,
1087
- :input => input)
1088
-
1089
- req.POST["fileupload"][:tempfile].size.must_equal 4
1090
- end
1091
-
1092
- it "use form_hash when form_input is a Tempfile" do
1093
- input = "{foo: 'bar'}"
1094
-
1095
- rack_input = Tempfile.new("rackspec")
1096
- rack_input.write(input)
1097
- rack_input.rewind
1098
-
1099
- req = make_request Rack::MockRequest.env_for("/",
1100
- "rack.request.form_hash" => {'foo' => 'bar'},
1101
- "rack.request.form_input" => rack_input,
1102
- :input => rack_input)
1103
-
1104
- req.POST.must_equal req.env['rack.request.form_hash']
1105
- end
1106
-
1107
- it "conform to the Rack spec" do
1108
- app = lambda { |env|
1109
- content = make_request(env).POST["file"].inspect
1110
- size = content.bytesize
1111
- [200, {"Content-Type" => "text/html", "Content-Length" => size.to_s}, [content]]
1112
- }
1113
-
1114
- input = <<EOF
1115
- --AaB03x\r
1116
- content-disposition: form-data; name="reply"\r
1117
- \r
1118
- yes\r
1119
- --AaB03x\r
1120
- content-disposition: form-data; name="fileupload"; filename="dj.jpg"\r
1121
- Content-Type: image/jpeg\r
1122
- Content-Transfer-Encoding: base64\r
1123
- \r
1124
- /9j/4AAQSkZJRgABAQAAAQABAAD//gA+Q1JFQVRPUjogZ2QtanBlZyB2MS4wICh1c2luZyBJSkcg\r
1125
- --AaB03x--\r
1126
- EOF
1127
- input.force_encoding(Encoding::ASCII_8BIT)
1128
- res = Rack::MockRequest.new(Rack::Lint.new(app)).get "/",
1129
- "CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
1130
- "CONTENT_LENGTH" => input.size.to_s, "rack.input" => StringIO.new(input)
1131
-
1132
- res.must_be :ok?
1133
- end
1134
-
1135
- it "parse Accept-Encoding correctly" do
1136
- parser = lambda do |x|
1137
- make_request(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
1138
- end
1139
-
1140
- parser.call(nil).must_equal []
1141
-
1142
- parser.call("compress, gzip").must_equal [["compress", 1.0], ["gzip", 1.0]]
1143
- parser.call("").must_equal []
1144
- parser.call("*").must_equal [["*", 1.0]]
1145
- parser.call("compress;q=0.5, gzip;q=1.0").must_equal [["compress", 0.5], ["gzip", 1.0]]
1146
- parser.call("gzip;q=1.0, identity; q=0.5, *;q=0").must_equal [["gzip", 1.0], ["identity", 0.5], ["*", 0] ]
1147
-
1148
- parser.call("gzip ; q=0.9").must_equal [["gzip", 0.9]]
1149
- parser.call("gzip ; deflate").must_equal [["gzip", 1.0]]
1150
- end
1151
-
1152
- it "parse Accept-Language correctly" do
1153
- parser = lambda do |x|
1154
- make_request(Rack::MockRequest.env_for("", "HTTP_ACCEPT_LANGUAGE" => x)).accept_language
1155
- end
1156
-
1157
- parser.call(nil).must_equal []
1158
-
1159
- parser.call("fr, en").must_equal [["fr", 1.0], ["en", 1.0]]
1160
- parser.call("").must_equal []
1161
- parser.call("*").must_equal [["*", 1.0]]
1162
- parser.call("fr;q=0.5, en;q=1.0").must_equal [["fr", 0.5], ["en", 1.0]]
1163
- parser.call("fr;q=1.0, en; q=0.5, *;q=0").must_equal [["fr", 1.0], ["en", 0.5], ["*", 0] ]
1164
-
1165
- parser.call("fr ; q=0.9").must_equal [["fr", 0.9]]
1166
- parser.call("fr").must_equal [["fr", 1.0]]
1167
- end
1168
-
1169
- def ip_app
1170
- lambda { |env|
1171
- request = make_request(env)
1172
- response = Rack::Response.new
1173
- response.write request.ip
1174
- response.finish
1175
- }
1176
- end
1177
-
1178
- it 'provide ip information' do
1179
- mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
1180
-
1181
- res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4'
1182
- res.body.must_equal '1.2.3.4'
1183
-
1184
- res = mock.get '/', 'REMOTE_ADDR' => 'fe80::202:b3ff:fe1e:8329'
1185
- res.body.must_equal 'fe80::202:b3ff:fe1e:8329'
1186
-
1187
- res = mock.get '/', 'REMOTE_ADDR' => '1.2.3.4,3.4.5.6'
1188
- res.body.must_equal '1.2.3.4'
1189
- end
1190
-
1191
- it 'deals with proxies' do
1192
- mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
1193
-
1194
- res = mock.get '/',
1195
- 'REMOTE_ADDR' => '1.2.3.4',
1196
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
1197
- res.body.must_equal '1.2.3.4'
1198
-
1199
- res = mock.get '/',
1200
- 'REMOTE_ADDR' => '1.2.3.4',
1201
- 'HTTP_X_FORWARDED_FOR' => 'unknown'
1202
- res.body.must_equal '1.2.3.4'
1203
-
1204
- res = mock.get '/',
1205
- 'REMOTE_ADDR' => '127.0.0.1',
1206
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
1207
- res.body.must_equal '3.4.5.6'
1208
-
1209
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,3.4.5.6'
1210
- res.body.must_equal '3.4.5.6'
1211
-
1212
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '192.168.0.1,3.4.5.6'
1213
- res.body.must_equal '3.4.5.6'
1214
-
1215
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '10.0.0.1,3.4.5.6'
1216
- res.body.must_equal '3.4.5.6'
1217
-
1218
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '10.0.0.1, 10.0.0.1, 3.4.5.6'
1219
- res.body.must_equal '3.4.5.6'
1220
-
1221
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '127.0.0.1, 3.4.5.6'
1222
- res.body.must_equal '3.4.5.6'
1223
-
1224
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,192.168.0.1'
1225
- res.body.must_equal 'unknown'
1226
-
1227
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'other,unknown,192.168.0.1'
1228
- res.body.must_equal 'unknown'
1229
-
1230
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'unknown,localhost,192.168.0.1'
1231
- res.body.must_equal 'unknown'
1232
-
1233
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '9.9.9.9, 3.4.5.6, 10.0.0.1, 172.31.4.4'
1234
- res.body.must_equal '3.4.5.6'
1235
-
1236
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '::1,2620:0:1c00:0:812c:9583:754b:ca11'
1237
- res.body.must_equal '2620:0:1c00:0:812c:9583:754b:ca11'
1238
-
1239
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '2620:0:1c00:0:812c:9583:754b:ca11,::1'
1240
- res.body.must_equal '2620:0:1c00:0:812c:9583:754b:ca11'
1241
-
1242
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => 'fd5b:982e:9130:247f:0000:0000:0000:0000,2620:0:1c00:0:812c:9583:754b:ca11'
1243
- res.body.must_equal '2620:0:1c00:0:812c:9583:754b:ca11'
1244
-
1245
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '2620:0:1c00:0:812c:9583:754b:ca11,fd5b:982e:9130:247f:0000:0000:0000:0000'
1246
- res.body.must_equal '2620:0:1c00:0:812c:9583:754b:ca11'
1247
-
1248
- res = mock.get '/',
1249
- 'HTTP_X_FORWARDED_FOR' => '1.1.1.1, 127.0.0.1',
1250
- 'HTTP_CLIENT_IP' => '1.1.1.1'
1251
- res.body.must_equal '1.1.1.1'
1252
-
1253
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, 9.9.9.9'
1254
- res.body.must_equal '9.9.9.9'
1255
-
1256
- res = mock.get '/', 'HTTP_X_FORWARDED_FOR' => '8.8.8.8, fe80::202:b3ff:fe1e:8329'
1257
- res.body.must_equal 'fe80::202:b3ff:fe1e:8329'
1258
-
1259
- # Unix Sockets
1260
- res = mock.get '/',
1261
- 'REMOTE_ADDR' => 'unix',
1262
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
1263
- res.body.must_equal '3.4.5.6'
1264
-
1265
- res = mock.get '/',
1266
- 'REMOTE_ADDR' => 'unix:/tmp/foo',
1267
- 'HTTP_X_FORWARDED_FOR' => '3.4.5.6'
1268
- res.body.must_equal '3.4.5.6'
1269
- end
1270
-
1271
- it "not allow IP spoofing via Client-IP and X-Forwarded-For headers" do
1272
- mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
1273
-
1274
- # IP Spoofing attempt:
1275
- # Client sends X-Forwarded-For: 6.6.6.6
1276
- # Client-IP: 6.6.6.6
1277
- # Load balancer adds X-Forwarded-For: 2.2.2.3, 192.168.0.7
1278
- # App receives: X-Forwarded-For: 6.6.6.6
1279
- # X-Forwarded-For: 2.2.2.3, 192.168.0.7
1280
- # Client-IP: 6.6.6.6
1281
- # Rack env: HTTP_X_FORWARDED_FOR: '6.6.6.6, 2.2.2.3, 192.168.0.7'
1282
- # HTTP_CLIENT_IP: '6.6.6.6'
1283
- res = mock.get '/',
1284
- 'HTTP_X_FORWARDED_FOR' => '6.6.6.6, 2.2.2.3, 192.168.0.7',
1285
- 'HTTP_CLIENT_IP' => '6.6.6.6'
1286
- res.body.must_equal '2.2.2.3'
1287
- end
1288
-
1289
- it "preserves ip for trusted proxy chain" do
1290
- mock = Rack::MockRequest.new(Rack::Lint.new(ip_app))
1291
- res = mock.get '/',
1292
- 'HTTP_X_FORWARDED_FOR' => '192.168.0.11, 192.168.0.7',
1293
- 'HTTP_CLIENT_IP' => '127.0.0.1'
1294
- res.body.must_equal '192.168.0.11'
1295
-
1296
- end
1297
-
1298
- it "regards local addresses as proxies" do
1299
- req = make_request(Rack::MockRequest.env_for("/"))
1300
- req.trusted_proxy?('127.0.0.1').must_equal 0
1301
- req.trusted_proxy?('10.0.0.1').must_equal 0
1302
- req.trusted_proxy?('172.16.0.1').must_equal 0
1303
- req.trusted_proxy?('172.20.0.1').must_equal 0
1304
- req.trusted_proxy?('172.30.0.1').must_equal 0
1305
- req.trusted_proxy?('172.31.0.1').must_equal 0
1306
- req.trusted_proxy?('192.168.0.1').must_equal 0
1307
- req.trusted_proxy?('::1').must_equal 0
1308
- req.trusted_proxy?('fd00::').must_equal 0
1309
- req.trusted_proxy?('localhost').must_equal 0
1310
- req.trusted_proxy?('unix').must_equal 0
1311
- req.trusted_proxy?('unix:/tmp/sock').must_equal 0
1312
-
1313
- req.trusted_proxy?("unix.example.org").must_be_nil
1314
- req.trusted_proxy?("example.org\n127.0.0.1").must_be_nil
1315
- req.trusted_proxy?("127.0.0.1\nexample.org").must_be_nil
1316
- req.trusted_proxy?("11.0.0.1").must_be_nil
1317
- req.trusted_proxy?("172.15.0.1").must_be_nil
1318
- req.trusted_proxy?("172.32.0.1").must_be_nil
1319
- req.trusted_proxy?("2001:470:1f0b:18f8::1").must_be_nil
1320
- end
1321
-
1322
- it "sets the default session to an empty hash" do
1323
- req = make_request(Rack::MockRequest.env_for("http://example.com:8080/"))
1324
- assert_equal Hash.new, req.session
1325
- end
1326
-
1327
- class MyRequest < Rack::Request
1328
- def params
1329
- {:foo => "bar"}
1330
- end
1331
- end
1332
-
1333
- it "allow subclass request to be instantiated after parent request" do
1334
- env = Rack::MockRequest.env_for("/?foo=bar")
1335
-
1336
- req1 = make_request(env)
1337
- req1.GET.must_equal "foo" => "bar"
1338
- req1.params.must_equal "foo" => "bar"
1339
-
1340
- req2 = MyRequest.new(env)
1341
- req2.GET.must_equal "foo" => "bar"
1342
- req2.params.must_equal :foo => "bar"
1343
- end
1344
-
1345
- it "allow parent request to be instantiated after subclass request" do
1346
- env = Rack::MockRequest.env_for("/?foo=bar")
1347
-
1348
- req1 = MyRequest.new(env)
1349
- req1.GET.must_equal "foo" => "bar"
1350
- req1.params.must_equal :foo => "bar"
1351
-
1352
- req2 = make_request(env)
1353
- req2.GET.must_equal "foo" => "bar"
1354
- req2.params.must_equal "foo" => "bar"
1355
- end
1356
-
1357
- it "raise TypeError every time if request parameters are broken" do
1358
- broken_query = Rack::MockRequest.env_for("/?foo%5B%5D=0&foo%5Bbar%5D=1")
1359
- req = make_request(broken_query)
1360
- lambda{req.GET}.must_raise TypeError
1361
- lambda{req.params}.must_raise TypeError
1362
- end
1363
-
1364
- (0x20...0x7E).collect { |a|
1365
- b = a.chr
1366
- c = CGI.escape(b)
1367
- it "not strip '#{a}' => '#{c}' => '#{b}' escaped character from parameters when accessed as string" do
1368
- url = "/?foo=#{c}bar#{c}"
1369
- env = Rack::MockRequest.env_for(url)
1370
- req2 = make_request(env)
1371
- req2.GET.must_equal "foo" => "#{b}bar#{b}"
1372
- req2.params.must_equal "foo" => "#{b}bar#{b}"
1373
- end
1374
- }
1375
-
1376
- class NonDelegate < Rack::Request
1377
- def delegate?; false; end
1378
- end
1379
-
1380
- def make_request(env)
1381
- NonDelegate.new env
1382
- end
1383
-
1384
- class TestProxyRequest < RackRequestTest
1385
- class DelegateRequest
1386
- include Rack::Request::Helpers
1387
- extend Forwardable
1388
-
1389
- def_delegators :@req, :has_header?, :get_header, :fetch_header,
1390
- :each_header, :set_header, :add_header, :delete_header
1391
-
1392
- def_delegators :@req, :[], :[]=, :values_at
1393
-
1394
- def initialize(req)
1395
- @req = req
1396
- end
1397
-
1398
- def delegate?; true; end
1399
-
1400
- def env; @req.env.dup; end
1401
- end
1402
-
1403
- def make_request(env)
1404
- DelegateRequest.new super(env)
1405
- end
1406
- end
1407
- end