rack 1.1.0 → 1.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +23 -26
- data/SPEC +3 -3
- data/lib/rack/auth/digest/params.rb +1 -1
- data/lib/rack/content_length.rb +1 -1
- data/lib/rack/etag.rb +15 -6
- data/lib/rack/file.rb +3 -1
- data/lib/rack/handler/cgi.rb +8 -7
- data/lib/rack/handler/fastcgi.rb +1 -1
- data/lib/rack/handler/lsws.rb +1 -1
- data/lib/rack/handler/mongrel.rb +1 -1
- data/lib/rack/handler/scgi.rb +1 -4
- data/lib/rack/handler/webrick.rb +10 -6
- data/lib/rack/lint.rb +29 -37
- data/lib/rack/mime.rb +2 -0
- data/lib/rack/mock.rb +2 -1
- data/lib/rack/recursive.rb +4 -0
- data/lib/rack/request.rb +8 -6
- data/lib/rack/response.rb +1 -0
- data/lib/rack/rewindable_input.rb +13 -10
- data/lib/rack/sendfile.rb +8 -6
- data/lib/rack/server.rb +66 -7
- data/lib/rack/session/memcache.rb +1 -1
- data/lib/rack/urlmap.rb +6 -7
- data/lib/rack/utils.rb +64 -22
- data/lib/rack.rb +1 -12
- data/rack.gemspec +6 -6
- data/spec/cgi/lighttpd.conf +25 -0
- data/spec/cgi/rackup_stub.rb +6 -0
- data/spec/cgi/sample_rackup.ru +5 -0
- data/spec/cgi/test +9 -0
- data/spec/cgi/test.fcgi +8 -0
- data/spec/cgi/test.ru +5 -0
- data/spec/multipart/bad_robots +259 -0
- data/spec/multipart/binary +0 -0
- data/spec/multipart/empty +10 -0
- data/spec/multipart/fail_16384_nofile +814 -0
- data/spec/multipart/file1.txt +1 -0
- data/spec/multipart/filename_and_modification_param +7 -0
- data/spec/multipart/filename_with_escaped_quotes +6 -0
- data/spec/multipart/filename_with_escaped_quotes_and_modification_param +7 -0
- data/spec/multipart/filename_with_percent_escaped_quotes +6 -0
- data/spec/multipart/filename_with_unescaped_quotes +6 -0
- data/spec/multipart/ie +6 -0
- data/spec/multipart/nested +10 -0
- data/spec/multipart/none +9 -0
- data/spec/multipart/semicolon +6 -0
- data/spec/multipart/text +10 -0
- data/spec/rackup/config.ru +31 -0
- data/{test/spec_rack_auth_basic.rb → spec/spec_auth_basic.rb} +11 -14
- data/{test/spec_rack_auth_digest.rb → spec/spec_auth_digest.rb} +18 -21
- data/{test/spec_rack_builder.rb → spec/spec_builder.rb} +49 -10
- data/{test/spec_rack_cascade.rb → spec/spec_cascade.rb} +7 -10
- data/{test/spec_rack_cgi.rb → spec/spec_cgi.rb} +34 -32
- data/{test/spec_rack_chunked.rb → spec/spec_chunked.rb} +8 -10
- data/{test/spec_rack_commonlogger.rb → spec/spec_commonlogger.rb} +10 -15
- data/{test/spec_rack_conditionalget.rb → spec/spec_conditionalget.rb} +5 -7
- data/{test/spec_rack_config.rb → spec/spec_config.rb} +6 -7
- data/{test/spec_rack_content_length.rb → spec/spec_content_length.rb} +7 -8
- data/{test/spec_rack_content_type.rb → spec/spec_content_type.rb} +5 -6
- data/{test/spec_rack_deflater.rb → spec/spec_deflater.rb} +11 -13
- data/{test/spec_rack_directory.rb → spec/spec_directory.rb} +6 -10
- data/{test/spec_rack_etag.rb → spec/spec_etag.rb} +3 -5
- data/{test/spec_rack_fastcgi.rb → spec/spec_fastcgi.rb} +36 -29
- data/{test/spec_rack_file.rb → spec/spec_file.rb} +9 -13
- data/{test/spec_rack_handler.rb → spec/spec_handler.rb} +10 -12
- data/{test/spec_rack_head.rb → spec/spec_head.rb} +3 -3
- data/{test/spec_rack_lint.rb → spec/spec_lint.rb} +19 -32
- data/{test/spec_rack_lobster.rb → spec/spec_lobster.rb} +9 -11
- data/{test/spec_rack_lock.rb → spec/spec_lock.rb} +15 -17
- data/{test/spec_rack_logger.rb → spec/spec_logger.rb} +6 -7
- data/{test/spec_rack_methodoverride.rb → spec/spec_methodoverride.rb} +15 -17
- data/{test/spec_rack_mock.rb → spec/spec_mock.rb} +30 -32
- data/{test/spec_rack_mongrel.rb → spec/spec_mongrel.rb} +40 -46
- data/{test/spec_rack_nulllogger.rb → spec/spec_nulllogger.rb} +4 -5
- data/{test/spec_rack_recursive.rb → spec/spec_recursive.rb} +28 -36
- data/{test/spec_rack_request.rb → spec/spec_request.rb} +84 -49
- data/{test/spec_rack_response.rb → spec/spec_response.rb} +48 -29
- data/spec/spec_rewindable_input.rb +118 -0
- data/{test/spec_rack_runtime.rb → spec/spec_runtime.rb} +15 -11
- data/{test/spec_rack_sendfile.rb → spec/spec_sendfile.rb} +11 -14
- data/{test/spec_rack_session_cookie.rb → spec/spec_session_cookie.rb} +15 -18
- data/{test/spec_rack_session_memcache.rb → spec/spec_session_memcache.rb} +32 -26
- data/{test/spec_rack_session_pool.rb → spec/spec_session_pool.rb} +36 -31
- data/spec/spec_showexceptions.rb +23 -0
- data/spec/spec_showstatus.rb +79 -0
- data/{test/spec_rack_static.rb → spec/spec_static.rb} +5 -9
- data/{test/spec_rack_thin.rb → spec/spec_thin.rb} +30 -35
- data/{test/spec_rack_urlmap.rb → spec/spec_urlmap.rb} +6 -8
- data/{test/spec_rack_utils.rb → spec/spec_utils.rb} +136 -71
- data/{test/spec_rack_webrick.rb → spec/spec_webrick.rb} +28 -36
- data/spec/testrequest.rb +77 -0
- data/spec/unregistered_handler/rack/handler/unregistered.rb +7 -0
- data/spec/unregistered_handler/rack/handler/unregistered_long_one.rb +7 -0
- metadata +206 -124
- data/RDOX +0 -0
- data/lib/rack/adapter/camping.rb +0 -22
- data/test/spec_rack_camping.rb +0 -51
- data/test/spec_rack_rewindable_input.rb +0 -118
- data/test/spec_rack_showexceptions.rb +0 -21
- data/test/spec_rack_showstatus.rb +0 -72
- data/test/spec_rackup.rb +0 -154
|
@@ -1,37 +1,32 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
|
-
|
|
3
1
|
begin
|
|
2
|
+
require 'rack'
|
|
4
3
|
require 'rack/handler/mongrel'
|
|
5
|
-
require '
|
|
6
|
-
require 'rack/lint'
|
|
7
|
-
require 'testrequest'
|
|
4
|
+
require File.expand_path('../testrequest', __FILE__)
|
|
8
5
|
require 'timeout'
|
|
9
6
|
|
|
10
7
|
Thread.abort_on_exception = true
|
|
11
8
|
$tcp_defer_accept_opts = nil
|
|
12
9
|
$tcp_cork_opts = nil
|
|
13
10
|
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
describe Rack::Handler::Mongrel do
|
|
12
|
+
extend TestRequest::Helpers
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
@acc = server.run
|
|
24
|
-
end
|
|
14
|
+
@server = Mongrel::HttpServer.new(@host='0.0.0.0', @port=9201)
|
|
15
|
+
@server.register('/test',
|
|
16
|
+
Rack::Handler::Mongrel.new(Rack::Lint.new(TestRequest.new)))
|
|
17
|
+
@server.register('/stream',
|
|
18
|
+
Rack::Handler::Mongrel.new(Rack::Lint.new(StreamingRequest)))
|
|
19
|
+
@acc = @server.run
|
|
25
20
|
|
|
26
|
-
|
|
21
|
+
should "respond" do
|
|
27
22
|
lambda {
|
|
28
23
|
GET("/test")
|
|
29
24
|
}.should.not.raise
|
|
30
25
|
end
|
|
31
26
|
|
|
32
|
-
|
|
27
|
+
should "be a Mongrel" do
|
|
33
28
|
GET("/test")
|
|
34
|
-
status.should.
|
|
29
|
+
status.should.equal 200
|
|
35
30
|
response["SERVER_SOFTWARE"].should =~ /Mongrel/
|
|
36
31
|
response["HTTP_VERSION"].should.equal "HTTP/1.1"
|
|
37
32
|
response["SERVER_PROTOCOL"].should.equal "HTTP/1.1"
|
|
@@ -39,15 +34,15 @@ context "Rack::Handler::Mongrel" do
|
|
|
39
34
|
response["SERVER_NAME"].should.equal "0.0.0.0"
|
|
40
35
|
end
|
|
41
36
|
|
|
42
|
-
|
|
37
|
+
should "have rack headers" do
|
|
43
38
|
GET("/test")
|
|
44
39
|
response["rack.version"].should.equal [1,1]
|
|
45
|
-
response["rack.multithread"].should.be
|
|
46
|
-
response["rack.multiprocess"].should.be
|
|
47
|
-
response["rack.run_once"].should.be
|
|
40
|
+
response["rack.multithread"].should.be.true
|
|
41
|
+
response["rack.multiprocess"].should.be.false
|
|
42
|
+
response["rack.run_once"].should.be.false
|
|
48
43
|
end
|
|
49
44
|
|
|
50
|
-
|
|
45
|
+
should "have CGI headers on GET" do
|
|
51
46
|
GET("/test")
|
|
52
47
|
response["REQUEST_METHOD"].should.equal "GET"
|
|
53
48
|
response["SCRIPT_NAME"].should.equal "/test"
|
|
@@ -64,7 +59,7 @@ context "Rack::Handler::Mongrel" do
|
|
|
64
59
|
response["QUERY_STRING"].should.equal "quux=1"
|
|
65
60
|
end
|
|
66
61
|
|
|
67
|
-
|
|
62
|
+
should "have CGI headers on POST" do
|
|
68
63
|
POST("/test", {"rack-form-data" => "23"}, {'X-test-header' => '42'})
|
|
69
64
|
status.should.equal 200
|
|
70
65
|
response["REQUEST_METHOD"].should.equal "POST"
|
|
@@ -75,18 +70,18 @@ context "Rack::Handler::Mongrel" do
|
|
|
75
70
|
response["test.postdata"].should.equal "rack-form-data=23"
|
|
76
71
|
end
|
|
77
72
|
|
|
78
|
-
|
|
73
|
+
should "support HTTP auth" do
|
|
79
74
|
GET("/test", {:user => "ruth", :passwd => "secret"})
|
|
80
75
|
response["HTTP_AUTHORIZATION"].should.equal "Basic cnV0aDpzZWNyZXQ="
|
|
81
76
|
end
|
|
82
77
|
|
|
83
|
-
|
|
78
|
+
should "set status" do
|
|
84
79
|
GET("/test?secret")
|
|
85
80
|
status.should.equal 403
|
|
86
81
|
response["rack.url_scheme"].should.equal "http"
|
|
87
82
|
end
|
|
88
83
|
|
|
89
|
-
|
|
84
|
+
should "provide a .run" do
|
|
90
85
|
block_ran = false
|
|
91
86
|
Thread.new {
|
|
92
87
|
Rack::Handler::Mongrel.run(lambda {}, {:Port => 9211}) { |server|
|
|
@@ -95,16 +90,16 @@ context "Rack::Handler::Mongrel" do
|
|
|
95
90
|
}
|
|
96
91
|
}
|
|
97
92
|
sleep 1
|
|
98
|
-
block_ran.should.be
|
|
93
|
+
block_ran.should.be.true
|
|
99
94
|
end
|
|
100
95
|
|
|
101
|
-
|
|
96
|
+
should "provide a .run that maps a hash" do
|
|
102
97
|
block_ran = false
|
|
103
98
|
Thread.new {
|
|
104
99
|
map = {'/'=>lambda{},'/foo'=>lambda{}}
|
|
105
100
|
Rack::Handler::Mongrel.run(map, :map => true, :Port => 9221) { |server|
|
|
106
101
|
server.should.be.kind_of Mongrel::HttpServer
|
|
107
|
-
server.classifier.uris.size.should.
|
|
102
|
+
server.classifier.uris.size.should.equal 2
|
|
108
103
|
server.classifier.uris.should.not.include '/arf'
|
|
109
104
|
server.classifier.uris.should.include '/'
|
|
110
105
|
server.classifier.uris.should.include '/foo'
|
|
@@ -112,16 +107,16 @@ context "Rack::Handler::Mongrel" do
|
|
|
112
107
|
}
|
|
113
108
|
}
|
|
114
109
|
sleep 1
|
|
115
|
-
block_ran.should.be
|
|
110
|
+
block_ran.should.be.true
|
|
116
111
|
end
|
|
117
112
|
|
|
118
|
-
|
|
113
|
+
should "provide a .run that maps a urlmap" do
|
|
119
114
|
block_ran = false
|
|
120
115
|
Thread.new {
|
|
121
116
|
map = Rack::URLMap.new({'/'=>lambda{},'/bar'=>lambda{}})
|
|
122
117
|
Rack::Handler::Mongrel.run(map, {:map => true, :Port => 9231}) { |server|
|
|
123
118
|
server.should.be.kind_of Mongrel::HttpServer
|
|
124
|
-
server.classifier.uris.size.should.
|
|
119
|
+
server.classifier.uris.size.should.equal 2
|
|
125
120
|
server.classifier.uris.should.not.include '/arf'
|
|
126
121
|
server.classifier.uris.should.include '/'
|
|
127
122
|
server.classifier.uris.should.include '/bar'
|
|
@@ -129,10 +124,10 @@ context "Rack::Handler::Mongrel" do
|
|
|
129
124
|
}
|
|
130
125
|
}
|
|
131
126
|
sleep 1
|
|
132
|
-
block_ran.should.be
|
|
127
|
+
block_ran.should.be.true
|
|
133
128
|
end
|
|
134
129
|
|
|
135
|
-
|
|
130
|
+
should "provide a .run that maps a urlmap restricting by host" do
|
|
136
131
|
block_ran = false
|
|
137
132
|
Thread.new {
|
|
138
133
|
map = Rack::URLMap.new({
|
|
@@ -148,22 +143,22 @@ context "Rack::Handler::Mongrel" do
|
|
|
148
143
|
Rack::Handler::Mongrel.run(map, opt) { |server|
|
|
149
144
|
server.should.be.kind_of Mongrel::HttpServer
|
|
150
145
|
server.classifier.uris.should.include '/'
|
|
151
|
-
server.classifier.handler_map['/'].size.should.
|
|
146
|
+
server.classifier.handler_map['/'].size.should.equal 2
|
|
152
147
|
server.classifier.uris.should.include '/foo'
|
|
153
|
-
server.classifier.handler_map['/foo'].size.should.
|
|
148
|
+
server.classifier.handler_map['/foo'].size.should.equal 1
|
|
154
149
|
server.classifier.uris.should.include '/bar'
|
|
155
|
-
server.classifier.handler_map['/bar'].size.should.
|
|
150
|
+
server.classifier.handler_map['/bar'].size.should.equal 2
|
|
156
151
|
server.classifier.uris.should.not.include '/qux'
|
|
157
152
|
server.classifier.uris.should.not.include '/arf'
|
|
158
|
-
server.classifier.uris.size.should.
|
|
153
|
+
server.classifier.uris.size.should.equal 3
|
|
159
154
|
block_ran = true
|
|
160
155
|
}
|
|
161
156
|
}
|
|
162
157
|
sleep 1
|
|
163
|
-
block_ran.should.be
|
|
158
|
+
block_ran.should.be.true
|
|
164
159
|
end
|
|
165
160
|
|
|
166
|
-
|
|
161
|
+
should "stream #each part of the response" do
|
|
167
162
|
body = ''
|
|
168
163
|
begin
|
|
169
164
|
Timeout.timeout(1) do
|
|
@@ -179,11 +174,10 @@ context "Rack::Handler::Mongrel" do
|
|
|
179
174
|
body.should.not.be.empty
|
|
180
175
|
end
|
|
181
176
|
|
|
182
|
-
|
|
183
|
-
@acc.raise Mongrel::StopServer
|
|
184
|
-
end
|
|
177
|
+
@acc.raise Mongrel::StopServer
|
|
185
178
|
end
|
|
186
179
|
|
|
187
|
-
rescue LoadError
|
|
188
|
-
|
|
180
|
+
rescue LoadError => ex
|
|
181
|
+
warn ex
|
|
182
|
+
warn "Skipping Rack::Handler::Mongrel tests (Mongrel is required). `gem install mongrel` and try again."
|
|
189
183
|
end
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
require 'rack/nulllogger'
|
|
2
|
-
require 'rack/lint'
|
|
3
|
-
require 'rack/mock'
|
|
4
2
|
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
describe Rack::NullLogger do
|
|
4
|
+
should "act as a noop logger" do
|
|
7
5
|
app = lambda { |env|
|
|
8
6
|
env['rack.logger'].warn "b00m"
|
|
9
7
|
[200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]]
|
|
10
8
|
}
|
|
11
|
-
Rack::NullLogger.new(app)
|
|
9
|
+
logger = Rack::NullLogger.new(app)
|
|
10
|
+
lambda{ logger.call({}) }.should.not.raise
|
|
12
11
|
end
|
|
13
12
|
end
|
|
@@ -1,53 +1,45 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
|
-
|
|
3
1
|
require 'rack/recursive'
|
|
4
|
-
require 'rack/urlmap'
|
|
5
|
-
require 'rack/response'
|
|
6
2
|
require 'rack/mock'
|
|
7
3
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
18
|
-
}
|
|
4
|
+
describe Rack::Recursive do
|
|
5
|
+
@app1 = lambda { |env|
|
|
6
|
+
res = Rack::Response.new
|
|
7
|
+
res["X-Path-Info"] = env["PATH_INFO"]
|
|
8
|
+
res["X-Query-String"] = env["QUERY_STRING"]
|
|
9
|
+
res.finish do |inner_res|
|
|
10
|
+
inner_res.write "App1"
|
|
11
|
+
end
|
|
12
|
+
}
|
|
19
13
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
14
|
+
@app2 = lambda { |env|
|
|
15
|
+
Rack::Response.new.finish do |res|
|
|
16
|
+
res.write "App2"
|
|
17
|
+
_, _, body = env['rack.recursive.include'].call(env, "/app1")
|
|
18
|
+
body.each { |b|
|
|
19
|
+
res.write b
|
|
20
|
+
}
|
|
21
|
+
end
|
|
22
|
+
}
|
|
29
23
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
@app3 = lambda { |env|
|
|
25
|
+
raise Rack::ForwardRequest.new("/app1")
|
|
26
|
+
}
|
|
33
27
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
end
|
|
28
|
+
@app4 = lambda { |env|
|
|
29
|
+
raise Rack::ForwardRequest.new("http://example.org/app1/quux?meh")
|
|
30
|
+
}
|
|
39
31
|
|
|
40
|
-
|
|
32
|
+
should "allow for subrequests" do
|
|
41
33
|
res = Rack::MockRequest.new(Rack::Recursive.new(
|
|
42
34
|
Rack::URLMap.new("/app1" => @app1,
|
|
43
35
|
"/app2" => @app2))).
|
|
44
36
|
get("/app2")
|
|
45
37
|
|
|
46
38
|
res.should.be.ok
|
|
47
|
-
res.body.should.equal "App2App1"
|
|
39
|
+
res.body.should.equal "App2App1"
|
|
48
40
|
end
|
|
49
41
|
|
|
50
|
-
|
|
42
|
+
should "raise error on requests not below the app" do
|
|
51
43
|
app = Rack::URLMap.new("/app1" => @app1,
|
|
52
44
|
"/app" => Rack::Recursive.new(
|
|
53
45
|
Rack::URLMap.new("/1" => @app1,
|
|
@@ -59,7 +51,7 @@ context "Rack::Recursive" do
|
|
|
59
51
|
message.should =~ /can only include below/
|
|
60
52
|
end
|
|
61
53
|
|
|
62
|
-
|
|
54
|
+
should "support forwarding" do
|
|
63
55
|
app = Rack::Recursive.new(Rack::URLMap.new("/app1" => @app1,
|
|
64
56
|
"/app3" => @app3,
|
|
65
57
|
"/app4" => @app4))
|
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
require 'test/spec'
|
|
2
1
|
require 'stringio'
|
|
3
|
-
|
|
2
|
+
require 'cgi'
|
|
4
3
|
require 'rack/request'
|
|
5
4
|
require 'rack/mock'
|
|
6
5
|
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
describe Rack::Request do
|
|
7
|
+
should "wrap the rack variables" do
|
|
9
8
|
req = Rack::Request.new(Rack::MockRequest.env_for("http://example.com:8080/"))
|
|
10
9
|
|
|
11
10
|
req.body.should.respond_to? :gets
|
|
@@ -29,7 +28,7 @@ context "Rack::Request" do
|
|
|
29
28
|
req.content_type.should.be.nil
|
|
30
29
|
end
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
should "figure out the correct host" do
|
|
33
32
|
req = Rack::Request.new \
|
|
34
33
|
Rack::MockRequest.env_for("/", "HTTP_HOST" => "www2.example.org")
|
|
35
34
|
req.host.should.equal "www2.example.org"
|
|
@@ -53,7 +52,7 @@ context "Rack::Request" do
|
|
|
53
52
|
req.host.should.equal ""
|
|
54
53
|
end
|
|
55
54
|
|
|
56
|
-
|
|
55
|
+
should "parse the query string" do
|
|
57
56
|
req = Rack::Request.new(Rack::MockRequest.env_for("/?foo=bar&quux=bla"))
|
|
58
57
|
req.query_string.should.equal "foo=bar&quux=bla"
|
|
59
58
|
req.GET.should.equal "foo" => "bar", "quux" => "bla"
|
|
@@ -61,12 +60,12 @@ context "Rack::Request" do
|
|
|
61
60
|
req.params.should.equal "foo" => "bar", "quux" => "bla"
|
|
62
61
|
end
|
|
63
62
|
|
|
64
|
-
|
|
63
|
+
should "raise if rack.input is missing" do
|
|
65
64
|
req = Rack::Request.new({})
|
|
66
65
|
lambda { req.POST }.should.raise(RuntimeError)
|
|
67
66
|
end
|
|
68
67
|
|
|
69
|
-
|
|
68
|
+
should "parse POST data when method is POST and no Content-Type given" do
|
|
70
69
|
req = Rack::Request.new \
|
|
71
70
|
Rack::MockRequest.env_for("/?foo=quux",
|
|
72
71
|
"REQUEST_METHOD" => 'POST',
|
|
@@ -79,7 +78,7 @@ context "Rack::Request" do
|
|
|
79
78
|
req.params.should.equal "foo" => "bar", "quux" => "bla"
|
|
80
79
|
end
|
|
81
80
|
|
|
82
|
-
|
|
81
|
+
should "parse POST data with explicit content type regardless of method" do
|
|
83
82
|
req = Rack::Request.new \
|
|
84
83
|
Rack::MockRequest.env_for("/",
|
|
85
84
|
"CONTENT_TYPE" => 'application/x-www-form-urlencoded;foo=bar',
|
|
@@ -91,7 +90,7 @@ context "Rack::Request" do
|
|
|
91
90
|
req.params.should.equal "foo" => "bar", "quux" => "bla"
|
|
92
91
|
end
|
|
93
92
|
|
|
94
|
-
|
|
93
|
+
should "not parse POST data when media type is not form-data" do
|
|
95
94
|
req = Rack::Request.new \
|
|
96
95
|
Rack::MockRequest.env_for("/?foo=quux",
|
|
97
96
|
"REQUEST_METHOD" => 'POST',
|
|
@@ -105,7 +104,7 @@ context "Rack::Request" do
|
|
|
105
104
|
req.body.read.should.equal "foo=bar&quux=bla"
|
|
106
105
|
end
|
|
107
106
|
|
|
108
|
-
|
|
107
|
+
should "parse POST data on PUT when media type is form-data" do
|
|
109
108
|
req = Rack::Request.new \
|
|
110
109
|
Rack::MockRequest.env_for("/?foo=quux",
|
|
111
110
|
"REQUEST_METHOD" => 'PUT',
|
|
@@ -115,7 +114,7 @@ context "Rack::Request" do
|
|
|
115
114
|
req.body.read.should.equal "foo=bar&quux=bla"
|
|
116
115
|
end
|
|
117
116
|
|
|
118
|
-
|
|
117
|
+
should "rewind input after parsing POST data" do
|
|
119
118
|
input = StringIO.new("foo=bar&quux=bla")
|
|
120
119
|
req = Rack::Request.new \
|
|
121
120
|
Rack::MockRequest.env_for("/",
|
|
@@ -125,21 +124,21 @@ context "Rack::Request" do
|
|
|
125
124
|
input.read.should.equal "foo=bar&quux=bla"
|
|
126
125
|
end
|
|
127
126
|
|
|
128
|
-
|
|
127
|
+
should "clean up Safari's ajax POST body" do
|
|
129
128
|
req = Rack::Request.new \
|
|
130
129
|
Rack::MockRequest.env_for("/",
|
|
131
130
|
'REQUEST_METHOD' => 'POST', :input => "foo=bar&quux=bla\0")
|
|
132
131
|
req.POST.should.equal "foo" => "bar", "quux" => "bla"
|
|
133
132
|
end
|
|
134
133
|
|
|
135
|
-
|
|
134
|
+
should "get value by key from params with #[]" do
|
|
136
135
|
req = Rack::Request.new \
|
|
137
136
|
Rack::MockRequest.env_for("?foo=quux")
|
|
138
137
|
req['foo'].should.equal 'quux'
|
|
139
138
|
req[:foo].should.equal 'quux'
|
|
140
139
|
end
|
|
141
140
|
|
|
142
|
-
|
|
141
|
+
should "set value to key on params with #[]=" do
|
|
143
142
|
req = Rack::Request.new \
|
|
144
143
|
Rack::MockRequest.env_for("?foo=duh")
|
|
145
144
|
req['foo'].should.equal 'duh'
|
|
@@ -157,7 +156,7 @@ context "Rack::Request" do
|
|
|
157
156
|
req[:foo].should.equal 'jaz'
|
|
158
157
|
end
|
|
159
158
|
|
|
160
|
-
|
|
159
|
+
should "return values for the keys in the order given from values_at" do
|
|
161
160
|
req = Rack::Request.new \
|
|
162
161
|
Rack::MockRequest.env_for("?foo=baz&wun=der&bar=ful")
|
|
163
162
|
req.values_at('foo').should.equal ['baz']
|
|
@@ -165,7 +164,7 @@ context "Rack::Request" do
|
|
|
165
164
|
req.values_at('bar', 'foo', 'wun').should.equal ['ful', 'baz', 'der']
|
|
166
165
|
end
|
|
167
166
|
|
|
168
|
-
|
|
167
|
+
should "extract referrer correctly" do
|
|
169
168
|
req = Rack::Request.new \
|
|
170
169
|
Rack::MockRequest.env_for("/", "HTTP_REFERER" => "/some/path")
|
|
171
170
|
req.referer.should.equal "/some/path"
|
|
@@ -175,7 +174,7 @@ context "Rack::Request" do
|
|
|
175
174
|
req.referer.should.equal "/"
|
|
176
175
|
end
|
|
177
176
|
|
|
178
|
-
|
|
177
|
+
should "extract user agent correctly" do
|
|
179
178
|
req = Rack::Request.new \
|
|
180
179
|
Rack::MockRequest.env_for("/", "HTTP_USER_AGENT" => "Mozilla/4.0 (compatible)")
|
|
181
180
|
req.user_agent.should.equal "Mozilla/4.0 (compatible)"
|
|
@@ -185,7 +184,7 @@ context "Rack::Request" do
|
|
|
185
184
|
req.user_agent.should.equal nil
|
|
186
185
|
end
|
|
187
186
|
|
|
188
|
-
|
|
187
|
+
should "cache, but invalidates the cache" do
|
|
189
188
|
req = Rack::Request.new \
|
|
190
189
|
Rack::MockRequest.env_for("/?foo=quux",
|
|
191
190
|
"CONTENT_TYPE" => "application/x-www-form-urlencoded",
|
|
@@ -203,7 +202,7 @@ context "Rack::Request" do
|
|
|
203
202
|
req.POST.should.equal "foo" => "bla", "quux" => "bar"
|
|
204
203
|
end
|
|
205
204
|
|
|
206
|
-
|
|
205
|
+
should "figure out if called via XHR" do
|
|
207
206
|
req = Rack::Request.new(Rack::MockRequest.env_for(""))
|
|
208
207
|
req.should.not.be.xhr
|
|
209
208
|
|
|
@@ -212,7 +211,7 @@ context "Rack::Request" do
|
|
|
212
211
|
req.should.be.xhr
|
|
213
212
|
end
|
|
214
213
|
|
|
215
|
-
|
|
214
|
+
should "parse cookies" do
|
|
216
215
|
req = Rack::Request.new \
|
|
217
216
|
Rack::MockRequest.env_for("", "HTTP_COOKIE" => "foo=bar;quux=h&m")
|
|
218
217
|
req.cookies.should.equal "foo" => "bar", "quux" => "h&m"
|
|
@@ -221,13 +220,13 @@ context "Rack::Request" do
|
|
|
221
220
|
req.cookies.should.equal({})
|
|
222
221
|
end
|
|
223
222
|
|
|
224
|
-
|
|
223
|
+
should "parse cookies according to RFC 2109" do
|
|
225
224
|
req = Rack::Request.new \
|
|
226
225
|
Rack::MockRequest.env_for('', 'HTTP_COOKIE' => 'foo=bar;foo=car')
|
|
227
226
|
req.cookies.should.equal 'foo' => 'bar'
|
|
228
227
|
end
|
|
229
228
|
|
|
230
|
-
|
|
229
|
+
should "provide setters" do
|
|
231
230
|
req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
|
|
232
231
|
req.script_name.should.equal ""
|
|
233
232
|
req.script_name = "/foo"
|
|
@@ -240,12 +239,12 @@ context "Rack::Request" do
|
|
|
240
239
|
e["PATH_INFO"].should.equal "/foo"
|
|
241
240
|
end
|
|
242
241
|
|
|
243
|
-
|
|
244
|
-
req = Rack::Request.new(e=Rack::MockRequest.env_for(""))
|
|
245
|
-
req.env.should
|
|
242
|
+
should "provide the original env" do
|
|
243
|
+
req = Rack::Request.new(e = Rack::MockRequest.env_for(""))
|
|
244
|
+
req.env.should == e
|
|
246
245
|
end
|
|
247
246
|
|
|
248
|
-
|
|
247
|
+
should "restore the URL" do
|
|
249
248
|
Rack::Request.new(Rack::MockRequest.env_for("")).url.
|
|
250
249
|
should.equal "http://example.org/"
|
|
251
250
|
Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).url.
|
|
@@ -263,7 +262,7 @@ context "Rack::Request" do
|
|
|
263
262
|
should.equal "https://example.com:8080/foo?foo"
|
|
264
263
|
end
|
|
265
264
|
|
|
266
|
-
|
|
265
|
+
should "restore the full path" do
|
|
267
266
|
Rack::Request.new(Rack::MockRequest.env_for("")).fullpath.
|
|
268
267
|
should.equal "/"
|
|
269
268
|
Rack::Request.new(Rack::MockRequest.env_for("", "SCRIPT_NAME" => "/foo")).fullpath.
|
|
@@ -281,7 +280,7 @@ context "Rack::Request" do
|
|
|
281
280
|
should.equal "/foo?foo"
|
|
282
281
|
end
|
|
283
282
|
|
|
284
|
-
|
|
283
|
+
should "handle multiple media type parameters" do
|
|
285
284
|
req = Rack::Request.new \
|
|
286
285
|
Rack::MockRequest.env_for("/",
|
|
287
286
|
"CONTENT_TYPE" => 'text/plain; foo=BAR,baz=bizzle dizzle;BLING=bam')
|
|
@@ -295,7 +294,7 @@ context "Rack::Request" do
|
|
|
295
294
|
req.media_type_params['bling'].should.equal 'bam'
|
|
296
295
|
end
|
|
297
296
|
|
|
298
|
-
|
|
297
|
+
should "parse multipart form data" do
|
|
299
298
|
# Adapted from RFC 1867.
|
|
300
299
|
input = <<EOF
|
|
301
300
|
--AaB03x\r
|
|
@@ -334,7 +333,7 @@ EOF
|
|
|
334
333
|
f[:tempfile].size.should.equal 76
|
|
335
334
|
end
|
|
336
335
|
|
|
337
|
-
|
|
336
|
+
should "parse big multipart form data" do
|
|
338
337
|
input = <<EOF
|
|
339
338
|
--AaB03x\r
|
|
340
339
|
content-disposition: form-data; name="huge"; filename="huge"\r
|
|
@@ -356,7 +355,7 @@ EOF
|
|
|
356
355
|
req.POST["mean"][:tempfile].read.should.equal "--AaB03xha"
|
|
357
356
|
end
|
|
358
357
|
|
|
359
|
-
|
|
358
|
+
should "detect invalid multipart form data" do
|
|
360
359
|
input = <<EOF
|
|
361
360
|
--AaB03x\r
|
|
362
361
|
content-disposition: form-data; name="huge"; filename="huge"\r
|
|
@@ -395,12 +394,33 @@ EOF
|
|
|
395
394
|
lambda { req.POST }.should.raise(EOFError)
|
|
396
395
|
end
|
|
397
396
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
397
|
+
should "not try to interpret binary as utf8" do
|
|
398
|
+
if /regexp/.respond_to?(:kcode) # < 1.9
|
|
399
|
+
begin
|
|
400
|
+
original_kcode = $KCODE
|
|
401
|
+
$KCODE='UTF8'
|
|
402
|
+
|
|
403
|
+
input = <<EOF
|
|
404
|
+
--AaB03x\r
|
|
405
|
+
content-disposition: form-data; name="fileupload"; filename="junk.a"\r
|
|
406
|
+
content-type: application/octet-stream\r
|
|
407
|
+
\r
|
|
408
|
+
#{[0x36,0xCF,0x0A,0xF8].pack('c*')}\r
|
|
409
|
+
--AaB03x--\r
|
|
410
|
+
EOF
|
|
402
411
|
|
|
403
|
-
|
|
412
|
+
req = Rack::Request.new Rack::MockRequest.env_for("/",
|
|
413
|
+
"CONTENT_TYPE" => "multipart/form-data, boundary=AaB03x",
|
|
414
|
+
"CONTENT_LENGTH" => input.size,
|
|
415
|
+
:input => input)
|
|
416
|
+
|
|
417
|
+
lambda{req.POST}.should.not.raise(EOFError)
|
|
418
|
+
req.POST["fileupload"][:tempfile].size.should.equal 4
|
|
419
|
+
ensure
|
|
420
|
+
$KCODE = original_kcode
|
|
421
|
+
end
|
|
422
|
+
else # >= 1.9
|
|
423
|
+
input = <<EOF
|
|
404
424
|
--AaB03x\r
|
|
405
425
|
content-disposition: form-data; name="fileupload"; filename="junk.a"\r
|
|
406
426
|
content-type: application/octet-stream\r
|
|
@@ -416,13 +436,10 @@ EOF
|
|
|
416
436
|
|
|
417
437
|
lambda{req.POST}.should.not.raise(EOFError)
|
|
418
438
|
req.POST["fileupload"][:tempfile].size.should.equal 4
|
|
419
|
-
ensure
|
|
420
|
-
$KCODE = original_kcode
|
|
421
439
|
end
|
|
422
440
|
end
|
|
423
441
|
|
|
424
|
-
|
|
425
|
-
specify "should work around buggy 1.8.* Tempfile equality" do
|
|
442
|
+
should "work around buggy 1.8.* Tempfile equality" do
|
|
426
443
|
input = <<EOF
|
|
427
444
|
--AaB03x\r
|
|
428
445
|
content-disposition: form-data; name="huge"; filename="huge"\r
|
|
@@ -440,11 +457,11 @@ EOF
|
|
|
440
457
|
"CONTENT_LENGTH" => input.size,
|
|
441
458
|
:input => rack_input)
|
|
442
459
|
|
|
443
|
-
lambda
|
|
444
|
-
lambda
|
|
460
|
+
lambda{ req.POST }.should.not.raise
|
|
461
|
+
lambda{ req.POST }.should.not.raise("input re-processed!")
|
|
445
462
|
end
|
|
446
463
|
|
|
447
|
-
|
|
464
|
+
should "conform to the Rack spec" do
|
|
448
465
|
app = lambda { |env|
|
|
449
466
|
content = Rack::Request.new(env).POST["file"].inspect
|
|
450
467
|
size = content.respond_to?(:bytesize) ? content.bytesize : content.size
|
|
@@ -472,7 +489,7 @@ EOF
|
|
|
472
489
|
res.should.be.ok
|
|
473
490
|
end
|
|
474
491
|
|
|
475
|
-
|
|
492
|
+
should "parse Accept-Encoding correctly" do
|
|
476
493
|
parser = lambda do |x|
|
|
477
494
|
Rack::Request.new(Rack::MockRequest.env_for("", "HTTP_ACCEPT_ENCODING" => x)).accept_encoding
|
|
478
495
|
end
|
|
@@ -488,7 +505,7 @@ EOF
|
|
|
488
505
|
lambda { parser.call("gzip ; q=1.0") }.should.raise(RuntimeError)
|
|
489
506
|
end
|
|
490
507
|
|
|
491
|
-
|
|
508
|
+
should 'provide ip information' do
|
|
492
509
|
app = lambda { |env|
|
|
493
510
|
request = Rack::Request.new(env)
|
|
494
511
|
response = Rack::Response.new
|
|
@@ -510,7 +527,13 @@ EOF
|
|
|
510
527
|
'REMOTE_ADDR' => '123.123.123.123',
|
|
511
528
|
'HTTP_X_FORWARDED_FOR' => '234.234.234.234,212.212.212.212'
|
|
512
529
|
|
|
513
|
-
res.body.should.equal '
|
|
530
|
+
res.body.should.equal '234.234.234.234'
|
|
531
|
+
|
|
532
|
+
res = mock.get '/',
|
|
533
|
+
'REMOTE_ADDR' => '123.123.123.123',
|
|
534
|
+
'HTTP_X_FORWARDED_FOR' => 'unknown,234.234.234.234,212.212.212.212'
|
|
535
|
+
|
|
536
|
+
res.body.should.equal '234.234.234.234'
|
|
514
537
|
end
|
|
515
538
|
|
|
516
539
|
class MyRequest < Rack::Request
|
|
@@ -519,7 +542,7 @@ EOF
|
|
|
519
542
|
end
|
|
520
543
|
end
|
|
521
544
|
|
|
522
|
-
|
|
545
|
+
should "allow subclass request to be instantiated after parent request" do
|
|
523
546
|
env = Rack::MockRequest.env_for("/?foo=bar")
|
|
524
547
|
|
|
525
548
|
req1 = Rack::Request.new(env)
|
|
@@ -531,7 +554,7 @@ EOF
|
|
|
531
554
|
req2.params.should.equal :foo => "bar"
|
|
532
555
|
end
|
|
533
556
|
|
|
534
|
-
|
|
557
|
+
should "allow parent request to be instantiated after subclass request" do
|
|
535
558
|
env = Rack::MockRequest.env_for("/?foo=bar")
|
|
536
559
|
|
|
537
560
|
req1 = MyRequest.new(env)
|
|
@@ -542,4 +565,16 @@ EOF
|
|
|
542
565
|
req2.GET.should.equal "foo" => "bar"
|
|
543
566
|
req2.params.should.equal "foo" => "bar"
|
|
544
567
|
end
|
|
568
|
+
|
|
569
|
+
(0x20...0x7E).collect { |a|
|
|
570
|
+
b = a.chr
|
|
571
|
+
c = CGI.escape(b)
|
|
572
|
+
should "not strip '#{a}' => '#{c}' => '#{b}' escaped character from parameters when accessed as string" do
|
|
573
|
+
url = "/?foo=#{c}bar#{c}"
|
|
574
|
+
env = Rack::MockRequest.env_for(url)
|
|
575
|
+
req2 = Rack::Request.new(env)
|
|
576
|
+
req2.GET.should.equal "foo" => "#{b}bar#{b}"
|
|
577
|
+
req2.params.should.equal "foo" => "#{b}bar#{b}"
|
|
578
|
+
end
|
|
579
|
+
}
|
|
545
580
|
end
|