corntrace-rack-contrib 1.0.2

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.
Files changed (72) hide show
  1. data/AUTHORS +26 -0
  2. data/COPYING +18 -0
  3. data/README.rdoc +87 -0
  4. data/Rakefile +89 -0
  5. data/lib/rack/contrib/accept_format.rb +46 -0
  6. data/lib/rack/contrib/access.rb +85 -0
  7. data/lib/rack/contrib/backstage.rb +20 -0
  8. data/lib/rack/contrib/bounce_favicon.rb +16 -0
  9. data/lib/rack/contrib/callbacks.rb +37 -0
  10. data/lib/rack/contrib/config.rb +16 -0
  11. data/lib/rack/contrib/cookies.rb +50 -0
  12. data/lib/rack/contrib/csshttprequest.rb +39 -0
  13. data/lib/rack/contrib/deflect.rb +137 -0
  14. data/lib/rack/contrib/evil.rb +12 -0
  15. data/lib/rack/contrib/expectation_cascade.rb +32 -0
  16. data/lib/rack/contrib/garbagecollector.rb +14 -0
  17. data/lib/rack/contrib/host_meta.rb +47 -0
  18. data/lib/rack/contrib/jsonp.rb +78 -0
  19. data/lib/rack/contrib/lighttpd_script_name_fix.rb +16 -0
  20. data/lib/rack/contrib/locale.rb +31 -0
  21. data/lib/rack/contrib/mailexceptions.rb +120 -0
  22. data/lib/rack/contrib/nested_params.rb +143 -0
  23. data/lib/rack/contrib/not_found.rb +18 -0
  24. data/lib/rack/contrib/post_body_content_type_parser.rb +40 -0
  25. data/lib/rack/contrib/proctitle.rb +30 -0
  26. data/lib/rack/contrib/profiler.rb +108 -0
  27. data/lib/rack/contrib/relative_redirect.rb +44 -0
  28. data/lib/rack/contrib/response_cache.rb +59 -0
  29. data/lib/rack/contrib/response_headers.rb +24 -0
  30. data/lib/rack/contrib/route_exceptions.rb +49 -0
  31. data/lib/rack/contrib/runtime.rb +31 -0
  32. data/lib/rack/contrib/sendfile.rb +142 -0
  33. data/lib/rack/contrib/signals.rb +63 -0
  34. data/lib/rack/contrib/simple_endpoint.rb +81 -0
  35. data/lib/rack/contrib/static_cache.rb +93 -0
  36. data/lib/rack/contrib/time_zone.rb +25 -0
  37. data/lib/rack/contrib.rb +39 -0
  38. data/rack-contrib.gemspec +104 -0
  39. data/test/404.html +1 -0
  40. data/test/Maintenance.html +1 -0
  41. data/test/documents/test +1 -0
  42. data/test/mail_settings.rb +12 -0
  43. data/test/spec_rack_accept_format.rb +72 -0
  44. data/test/spec_rack_access.rb +154 -0
  45. data/test/spec_rack_backstage.rb +26 -0
  46. data/test/spec_rack_callbacks.rb +65 -0
  47. data/test/spec_rack_config.rb +22 -0
  48. data/test/spec_rack_contrib.rb +8 -0
  49. data/test/spec_rack_cookies.rb +56 -0
  50. data/test/spec_rack_csshttprequest.rb +66 -0
  51. data/test/spec_rack_deflect.rb +107 -0
  52. data/test/spec_rack_evil.rb +19 -0
  53. data/test/spec_rack_expectation_cascade.rb +72 -0
  54. data/test/spec_rack_garbagecollector.rb +13 -0
  55. data/test/spec_rack_host_meta.rb +50 -0
  56. data/test/spec_rack_jsonp.rb +83 -0
  57. data/test/spec_rack_lighttpd_script_name_fix.rb +16 -0
  58. data/test/spec_rack_mailexceptions.rb +97 -0
  59. data/test/spec_rack_nested_params.rb +46 -0
  60. data/test/spec_rack_not_found.rb +17 -0
  61. data/test/spec_rack_post_body_content_type_parser.rb +32 -0
  62. data/test/spec_rack_proctitle.rb +26 -0
  63. data/test/spec_rack_profiler.rb +37 -0
  64. data/test/spec_rack_relative_redirect.rb +78 -0
  65. data/test/spec_rack_response_cache.rb +137 -0
  66. data/test/spec_rack_response_headers.rb +35 -0
  67. data/test/spec_rack_runtime.rb +35 -0
  68. data/test/spec_rack_sendfile.rb +86 -0
  69. data/test/spec_rack_simple_endpoint.rb +95 -0
  70. data/test/spec_rack_static_cache.rb +91 -0
  71. data/test/statics/test +1 -0
  72. metadata +234 -0
@@ -0,0 +1,107 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/deflect'
4
+
5
+ context "Rack::Deflect" do
6
+
7
+ setup do
8
+ @app = lambda { |env| [200, { 'Content-Type' => 'text/plain' }, ['cookies']] }
9
+ @mock_addr_1 = '111.111.111.111'
10
+ @mock_addr_2 = '222.222.222.222'
11
+ @mock_addr_3 = '333.333.333.333'
12
+ end
13
+
14
+ def mock_env remote_addr, path = '/'
15
+ Rack::MockRequest.env_for path, { 'REMOTE_ADDR' => remote_addr }
16
+ end
17
+
18
+ def mock_deflect options = {}
19
+ Rack::Deflect.new @app, options
20
+ end
21
+
22
+ specify "should allow regular requests to follow through" do
23
+ app = mock_deflect
24
+ status, headers, body = app.call mock_env(@mock_addr_1)
25
+ status.should.equal 200
26
+ body.should.equal ['cookies']
27
+ end
28
+
29
+ specify "should deflect requests exceeding the request threshold" do
30
+ log = StringIO.new
31
+ app = mock_deflect :request_threshold => 5, :interval => 10, :block_duration => 10, :log => log
32
+ env = mock_env @mock_addr_1
33
+
34
+ # First 5 should be fine
35
+ 5.times do
36
+ status, headers, body = app.call env
37
+ status.should.equal 200
38
+ body.should.equal ['cookies']
39
+ end
40
+
41
+ # Remaining requests should fail for 10 seconds
42
+ 10.times do
43
+ status, headers, body = app.call env
44
+ status.should.equal 403
45
+ body.should.equal []
46
+ end
47
+
48
+ # Log should reflect that we have blocked an address
49
+ log.string.should.match(/^deflect\(\d+\/\d+\/\d+\): blocked 111.111.111.111\n/)
50
+ end
51
+
52
+ specify "should expire blocking" do
53
+ log = StringIO.new
54
+ app = mock_deflect :request_threshold => 5, :interval => 2, :block_duration => 2, :log => log
55
+ env = mock_env @mock_addr_1
56
+
57
+ # First 5 should be fine
58
+ 5.times do
59
+ status, headers, body = app.call env
60
+ status.should.equal 200
61
+ body.should.equal ['cookies']
62
+ end
63
+
64
+ # Exceeds request threshold
65
+ status, headers, body = app.call env
66
+ status.should.equal 403
67
+ body.should.equal []
68
+
69
+ # Allow block to expire
70
+ sleep 3
71
+
72
+ # Another 5 is fine now
73
+ 5.times do
74
+ status, headers, body = app.call env
75
+ status.should.equal 200
76
+ body.should.equal ['cookies']
77
+ end
78
+
79
+ # Log should reflect block and release
80
+ log.string.should.match(/deflect.*: blocked 111\.111\.111\.111\ndeflect.*: released 111\.111\.111\.111\n/)
81
+ end
82
+
83
+ specify "should allow whitelisting of remote addresses" do
84
+ app = mock_deflect :whitelist => [@mock_addr_1], :request_threshold => 5, :interval => 2
85
+ env = mock_env @mock_addr_1
86
+
87
+ # Whitelisted addresses are always fine
88
+ 10.times do
89
+ status, headers, body = app.call env
90
+ status.should.equal 200
91
+ body.should.equal ['cookies']
92
+ end
93
+ end
94
+
95
+ specify "should allow blacklisting of remote addresses" do
96
+ app = mock_deflect :blacklist => [@mock_addr_2]
97
+
98
+ status, headers, body = app.call mock_env(@mock_addr_1)
99
+ status.should.equal 200
100
+ body.should.equal ['cookies']
101
+
102
+ status, headers, body = app.call mock_env(@mock_addr_2)
103
+ status.should.equal 403
104
+ body.should.equal []
105
+ end
106
+
107
+ end
@@ -0,0 +1,19 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/evil'
4
+ require 'erb'
5
+
6
+ context "Rack::Evil" do
7
+ app = lambda do |env|
8
+ template = ERB.new("<%= throw :response, [404, {'Content-Type' => 'text/html'}, 'Never know where it comes from'] %>")
9
+ [200, {'Content-Type' => 'text/plain'}, template.result(binding)]
10
+ end
11
+
12
+ specify "should enable the app to return the response from anywhere" do
13
+ status, headers, body = Rack::Evil.new(app).call({})
14
+
15
+ status.should.equal 404
16
+ headers['Content-Type'].should.equal 'text/html'
17
+ body.should.equal 'Never know where it comes from'
18
+ end
19
+ end
@@ -0,0 +1,72 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/expectation_cascade'
4
+
5
+ context "Rack::ExpectationCascade" do
6
+ specify "with no apps returns a 404 if no expectation header was set" do
7
+ app = Rack::ExpectationCascade.new
8
+ env = {}
9
+ response = app.call(env)
10
+ response[0].should.equal 404
11
+ env.should.equal({})
12
+ end
13
+
14
+ specify "with no apps returns a 417 if expectation header was set" do
15
+ app = Rack::ExpectationCascade.new
16
+ env = {"Expect" => "100-continue"}
17
+ response = app.call(env)
18
+ response[0].should.equal 417
19
+ env.should.equal({"Expect" => "100-continue"})
20
+ end
21
+
22
+ specify "returns first successful response" do
23
+ app = Rack::ExpectationCascade.new do |cascade|
24
+ cascade << lambda { |env| [417, {"Content-Type" => "text/plain"}, []] }
25
+ cascade << lambda { |env| [200, {"Content-Type" => "text/plain"}, ["OK"]] }
26
+ end
27
+ response = app.call({})
28
+ response[0].should.equal 200
29
+ response[2][0].should.equal "OK"
30
+ end
31
+
32
+ specify "expectation is set if it has not been already" do
33
+ app = Rack::ExpectationCascade.new do |cascade|
34
+ cascade << lambda { |env| [200, {"Content-Type" => "text/plain"}, ["Expect: #{env["Expect"]}"]] }
35
+ end
36
+ response = app.call({})
37
+ response[0].should.equal 200
38
+ response[2][0].should.equal "Expect: 100-continue"
39
+ end
40
+
41
+ specify "returns a 404 if no apps where matched and no expectation header was set" do
42
+ app = Rack::ExpectationCascade.new do |cascade|
43
+ cascade << lambda { |env| [417, {"Content-Type" => "text/plain"}, []] }
44
+ end
45
+ response = app.call({})
46
+ response[0].should.equal 404
47
+ response[2][0].should.equal nil
48
+ end
49
+
50
+ specify "returns a 417 if no apps where matched and a expectation header was set" do
51
+ app = Rack::ExpectationCascade.new do |cascade|
52
+ cascade << lambda { |env| [417, {"Content-Type" => "text/plain"}, []] }
53
+ end
54
+ response = app.call({"Expect" => "100-continue"})
55
+ response[0].should.equal 417
56
+ response[2][0].should.equal nil
57
+ end
58
+
59
+ specify "nests expectation cascades" do
60
+ app = Rack::ExpectationCascade.new do |c1|
61
+ c1 << Rack::ExpectationCascade.new do |c2|
62
+ c2 << lambda { |env| [417, {"Content-Type" => "text/plain"}, []] }
63
+ end
64
+ c1 << Rack::ExpectationCascade.new do |c2|
65
+ c2 << lambda { |env| [200, {"Content-Type" => "text/plain"}, ["OK"]] }
66
+ end
67
+ end
68
+ response = app.call({})
69
+ response[0].should.equal 200
70
+ response[2][0].should.equal "OK"
71
+ end
72
+ end
@@ -0,0 +1,13 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/garbagecollector'
4
+
5
+ context 'Rack::GarbageCollector' do
6
+
7
+ specify 'starts the garbage collector after each request' do
8
+ app = lambda { |env|
9
+ [200, {'Content-Type'=>'text/plain'}, ['Hello World']] }
10
+ Rack::GarbageCollector.new(app).call({})
11
+ end
12
+
13
+ end
@@ -0,0 +1,50 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/host_meta'
4
+ require 'rack/contrib/not_found'
5
+
6
+ context "Rack::HostMeta" do
7
+
8
+ setup do
9
+ app = Rack::Builder.new do
10
+ use Rack::Lint
11
+ use Rack::ContentLength
12
+ use Rack::HostMeta do
13
+ link :uri => '/robots.txt', :rel => 'robots'
14
+ link :uri => '/w3c/p3p.xml', :rel => 'privacy', :type => 'application/p3p.xml'
15
+ link :pattern => '{uri};json_schema', :rel => 'describedby', :type => 'application/x-schema+json'
16
+ end
17
+ run Rack::NotFound.new('test/404.html')
18
+ end
19
+ @response = Rack::MockRequest.new(app).get('/host-meta')
20
+ end
21
+
22
+ specify "should respond to /host-meta" do
23
+ @response.status.should.equal 200
24
+ end
25
+
26
+ specify "should respond with the correct media type" do
27
+ @response['Content-Type'].should.equal 'application/host-meta'
28
+ end
29
+
30
+ specify "should include a Link entry for each Link item in the config block" do
31
+ @response.body.should.match(/Link:\s*<\/robots.txt>;.*\n/)
32
+ @response.body.should.match(/Link:\s*<\/w3c\/p3p.xml>;.*/)
33
+ end
34
+
35
+ specify "should include a Link-Pattern entry for each Link-Pattern item in the config" do
36
+ @response.body.should.match(/Link-Pattern:\s*<\{uri\};json_schema>;.*/)
37
+ end
38
+
39
+ specify "should include a rel attribute for each Link or Link-Pattern entry where specified" do
40
+ @response.body.should.match(/rel="robots"/)
41
+ @response.body.should.match(/rel="privacy"/)
42
+ @response.body.should.match(/rel="describedby"/)
43
+ end
44
+
45
+ specify "should include a type attribute for each Link or Link-Pattern entry where specified" do
46
+ @response.body.should.match(/Link:\s*<\/w3c\/p3p.xml>;.*type.*application\/p3p.xml/)
47
+ @response.body.should.match(/Link-Pattern:\s*<\{uri\};json_schema>;.*type.*application\/x-schema\+json/)
48
+ end
49
+
50
+ end
@@ -0,0 +1,83 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ # require File.expand_path(File.dirname(__FILE__)+"/../lib/rack/contrib/jsonp")
4
+ require 'rack/contrib/jsonp'
5
+
6
+ context "Rack::JSONP" do
7
+
8
+ context "when a callback parameter is provided" do
9
+ specify "should wrap the response body in the Javascript callback if JSON" do
10
+ test_body = '{"bar":"foo"}'
11
+ callback = 'foo'
12
+ app = lambda { |env| [200, {'Content-Type' => 'application/json'}, [test_body]] }
13
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
14
+ body = Rack::JSONP.new(app).call(request).last
15
+ body.should.equal ["#{callback}(#{test_body})"]
16
+ end
17
+
18
+ specify "should not wrap the response body in a callback if body is not JSON" do
19
+ test_body = '{"bar":"foo"}'
20
+ callback = 'foo'
21
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, [test_body]] }
22
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
23
+ body = Rack::JSONP.new(app).call(request).last
24
+ body.should.equal ['{"bar":"foo"}']
25
+ end
26
+
27
+ specify "should update content length if it was set" do
28
+ test_body = '{"bar":"foo"}'
29
+ callback = 'foo'
30
+ app = lambda { |env| [200, {'Content-Type' => 'application/json', 'Content-Length' => test_body.length}, [test_body]] }
31
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
32
+
33
+ headers = Rack::JSONP.new(app).call(request)[1]
34
+ expected_length = test_body.length + callback.length + "()".length
35
+ headers['Content-Length'].should.equal (expected_length.to_s)
36
+ end
37
+
38
+ specify "should not touch content length if not set" do
39
+ test_body = '{"bar":"foo"}'
40
+ callback = 'foo'
41
+ app = lambda { |env| [200, {'Content-Type' => 'application/json'}, [test_body]] }
42
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
43
+ headers = Rack::JSONP.new(app).call(request)[1]
44
+ headers['Content-Length'].should.equal nil
45
+ end
46
+
47
+ specify "should modify the content type to application/javascript" do
48
+ test_body = '{"bar":"foo"}'
49
+ callback = 'foo'
50
+ app = lambda { |env| [200, {'Content-Type' => 'application/json'}, [test_body]] }
51
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
52
+ headers = Rack::JSONP.new(app).call(request)[1]
53
+ headers['Content-Type'].should.equal ('application/javascript')
54
+ end
55
+
56
+ specify "should write status code to response and set status to 200 if status is 40x or 50x" do
57
+ callback = 'foo'
58
+ app = lambda { |env| [404, {'Content-Type' => 'application/json'}, [""]] }
59
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar&callback=#{callback}")
60
+ status, headers, body = Rack::JSONP.new(app).call(request)
61
+ status.should.equal 200
62
+ body.should.equal ["#{callback}({\"errorCode\":404})"]
63
+ end
64
+
65
+ end
66
+
67
+ specify "should not change anything if no callback param is provided" do
68
+ test_body = ['{"bar":"foo"}']
69
+ app = lambda { |env| [200, {'Content-Type' => 'application/json'}, test_body] }
70
+ request = Rack::MockRequest.env_for("/", :params => "foo=bar")
71
+ body = Rack::JSONP.new(app).call(request).last
72
+ body.should.equal test_body
73
+ end
74
+
75
+ specify "should not change anything if it's not a json response" do
76
+ test_body = '<html><body>404 Not Found</body></html>'
77
+ app = lambda { |env| [404, {'Content-Type' => 'text/html'}, [test_body]] }
78
+ request = Rack::MockRequest.env_for("/", :params => "callback=foo", 'HTTP_ACCEPT' => 'application/json')
79
+ body = Rack::JSONP.new(app).call(request).last
80
+ body.should.equal [test_body]
81
+ end
82
+
83
+ end
@@ -0,0 +1,16 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/lighttpd_script_name_fix'
4
+
5
+ context "Rack::LighttpdScriptNameFix" do
6
+ specify "corrects SCRIPT_NAME and PATH_INFO set by lighttpd " do
7
+ env = {
8
+ "PATH_INFO" => "/foo/bar/baz",
9
+ "SCRIPT_NAME" => "/hello"
10
+ }
11
+ app = lambda { |_| [200, {'Content-Type' => 'text/plain'}, ["Hello, World!"]] }
12
+ response = Rack::LighttpdScriptNameFix.new(app).call(env)
13
+ env['SCRIPT_NAME'].should.be.empty
14
+ env['PATH_INFO'].should.equal '/hello/foo/bar/baz'
15
+ end
16
+ end
@@ -0,0 +1,97 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+
4
+ begin
5
+ require 'tmail'
6
+ require 'rack/contrib/mailexceptions'
7
+
8
+ require File.dirname(__FILE__) + '/mail_settings.rb'
9
+
10
+ class TestError < RuntimeError
11
+ end
12
+
13
+ def test_exception
14
+ raise TestError, 'Suffering Succotash!'
15
+ rescue => boom
16
+ return boom
17
+ end
18
+
19
+ context 'Rack::MailExceptions' do
20
+
21
+ setup do
22
+ @app = lambda { |env| raise TestError, 'Why, I say' }
23
+ @env = Rack::MockRequest.env_for("/foo",
24
+ 'FOO' => 'BAR',
25
+ :method => 'GET',
26
+ :input => 'THE BODY'
27
+ )
28
+ @smtp_settings = {
29
+ :server => 'example.com',
30
+ :domain => 'example.com',
31
+ :port => 500,
32
+ :authentication => :login,
33
+ :user_name => 'joe',
34
+ :password => 'secret'
35
+ }
36
+ end
37
+
38
+ specify 'yields a configuration object to the block when created' do
39
+ called = false
40
+ mailer =
41
+ Rack::MailExceptions.new(@app) do |mail|
42
+ called = true
43
+ mail.to 'foo@example.org'
44
+ mail.from 'bar@example.org'
45
+ mail.subject '[ERROR] %s'
46
+ mail.smtp @smtp_settings
47
+ end
48
+ called.should.be == true
49
+ end
50
+
51
+ specify 'generates a TMail object with configured settings' do
52
+ mailer =
53
+ Rack::MailExceptions.new(@app) do |mail|
54
+ mail.to 'foo@example.org'
55
+ mail.from 'bar@example.org'
56
+ mail.subject '[ERROR] %s'
57
+ mail.smtp @smtp_settings
58
+ end
59
+
60
+ tmail = mailer.send(:generate_mail, test_exception, @env)
61
+ tmail.to.should.equal ['foo@example.org']
62
+ tmail.from.should.equal ['bar@example.org']
63
+ tmail.subject.should.equal '[ERROR] Suffering Succotash!'
64
+ tmail.body.should.not.be.nil
65
+ tmail.body.should.be =~ /FOO:\s+"BAR"/
66
+ tmail.body.should.be =~ /^\s*THE BODY\s*$/
67
+ end
68
+
69
+ specify 'catches exceptions raised from app, sends mail, and re-raises' do
70
+ mailer =
71
+ Rack::MailExceptions.new(@app) do |mail|
72
+ mail.to 'foo@example.org'
73
+ mail.from 'bar@example.org'
74
+ mail.subject '[ERROR] %s'
75
+ mail.smtp @smtp_settings
76
+ end
77
+ lambda { mailer.call(@env) }.should.raise(TestError)
78
+ @env['mail.sent'].should.be == true
79
+ end
80
+
81
+ if TEST_SMTP && ! TEST_SMTP.empty?
82
+ specify 'sends mail' do
83
+ mailer =
84
+ Rack::MailExceptions.new(@app) do |mail|
85
+ mail.config.merge! TEST_SMTP
86
+ end
87
+ lambda { mailer.call(@env) }.should.raise(TestError)
88
+ @env['mail.sent'].should.be == true
89
+ end
90
+ else
91
+ STDERR.puts 'WARN: Skipping SMTP tests (edit test/mail_settings.rb to enable)'
92
+ end
93
+
94
+ end
95
+ rescue LoadError => boom
96
+ STDERR.puts "WARN: Skipping Rack::MailExceptions tests (tmail not installed)"
97
+ end
@@ -0,0 +1,46 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/nested_params'
4
+ require 'rack/methodoverride'
5
+
6
+ context Rack::NestedParams do
7
+
8
+ App = lambda { |env| [200, {'Content-Type' => 'text/plain'}, Rack::Request.new(env)] }
9
+
10
+ def env_for_post_with_headers(path, headers, body)
11
+ Rack::MockRequest.env_for(path, {:method => "POST", :input => body}.merge(headers))
12
+ end
13
+
14
+ def form_post(params, content_type = 'application/x-www-form-urlencoded')
15
+ params = Rack::Utils.build_query(params) if Hash === params
16
+ env_for_post_with_headers('/', {'CONTENT_TYPE' => content_type}, params)
17
+ end
18
+
19
+ def middleware
20
+ Rack::NestedParams.new(App)
21
+ end
22
+
23
+ specify "should handle requests with POST body Content-Type of application/x-www-form-urlencoded" do
24
+ req = middleware.call(form_post({'foo[bar][baz]' => 'nested'})).last
25
+ req.POST.should.equal({"foo" => { "bar" => { "baz" => "nested" }}})
26
+ end
27
+
28
+ specify "should not parse requests with other Content-Type" do
29
+ req = middleware.call(form_post({'foo[bar][baz]' => 'nested'}, 'text/plain')).last
30
+ req.POST.should.equal({})
31
+ end
32
+
33
+ specify "should work even after another middleware already parsed the request" do
34
+ app = Rack::MethodOverride.new(middleware)
35
+ req = app.call(form_post({'_method' => 'put', 'foo[bar]' => 'nested'})).last
36
+ req.POST.should.equal({'_method' => 'put', "foo" => { "bar" => "nested" }})
37
+ req.put?.should.equal true
38
+ end
39
+
40
+ specify "should make first boolean have precedence even after request already parsed" do
41
+ app = Rack::MethodOverride.new(middleware)
42
+ req = app.call(form_post("foo=1&foo=0")).last
43
+ req.POST.should.equal({"foo" => '1'})
44
+ end
45
+
46
+ end
@@ -0,0 +1,17 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/not_found'
4
+
5
+ context "Rack::NotFound" do
6
+
7
+ specify "should render the file at the given path for all requests" do
8
+ app = Rack::Builder.new do
9
+ use Rack::Lint
10
+ run Rack::NotFound.new('test/404.html')
11
+ end
12
+ response = Rack::MockRequest.new(app).get('/')
13
+ response.body.should.equal('Not Found')
14
+ response.status.should.equal(404)
15
+ end
16
+
17
+ end
@@ -0,0 +1,32 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+
4
+ begin
5
+ require 'rack/contrib/post_body_content_type_parser'
6
+
7
+ context "Rack::PostBodyContentTypeParser" do
8
+
9
+ specify "should handle requests with POST body Content-Type of application/json" do
10
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, Rack::Request.new(env).POST] }
11
+ env = env_for_post_with_headers('/', {'Content_Type'.upcase => 'application/json'}, {:body => "asdf", :status => "12"}.to_json)
12
+ body = Rack::PostBodyContentTypeParser.new(app).call(env).last
13
+ body['body'].should.equal "asdf"
14
+ body['status'].should.equal "12"
15
+ end
16
+
17
+ specify "should change nothing when the POST body content type isn't application/json" do
18
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, Rack::Request.new(env).POST] }
19
+ body = Rack::PostBodyContentTypeParser.new(app).call(Rack::MockRequest.env_for("/", {:method => 'POST', :params => "body=asdf&status=12"})).last
20
+ body['body'].should.equal "asdf"
21
+ body['status'].should.equal "12"
22
+ end
23
+
24
+ end
25
+
26
+ def env_for_post_with_headers(path, headers, body)
27
+ Rack::MockRequest.env_for(path, {:method => "POST", :input => body}.merge(headers))
28
+ end
29
+ rescue LoadError => e
30
+ # Missing dependency JSON, skipping tests.
31
+ STDERR.puts "WARN: Skipping Rack::PostBodyContentTypeParser tests (json not installed)"
32
+ end
@@ -0,0 +1,26 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+ require 'rack/contrib/proctitle'
4
+
5
+ context "Rack::ProcTitle" do
6
+ F = ::File
7
+
8
+ progname = File.basename($0)
9
+ appname = F.expand_path(__FILE__).split('/')[-3]
10
+
11
+ def simple_app(body=['Hello World!'])
12
+ lambda { |env| [200, {'Content-Type' => 'text/plain'}, body] }
13
+ end
14
+
15
+ specify "should set the process title when created" do
16
+ Rack::ProcTitle.new(simple_app)
17
+ $0.should.equal "#{progname} [#{appname}] init ..."
18
+ end
19
+
20
+ specify "should set the process title on each request" do
21
+ app = Rack::ProcTitle.new(simple_app)
22
+ req = Rack::MockRequest.new(app)
23
+ 10.times { req.get('/hello') }
24
+ $0.should.equal "#{progname} [#{appname}/80] (10) GET /hello"
25
+ end
26
+ end
@@ -0,0 +1,37 @@
1
+ require 'test/spec'
2
+ require 'rack/mock'
3
+
4
+ begin
5
+ require 'rack/contrib/profiler'
6
+
7
+ context 'Rack::Profiler' do
8
+ app = lambda { |env| [200, {'Content-Type' => 'text/plain'}, 'Oh hai der'] }
9
+ request = Rack::MockRequest.env_for("/", :params => "profile=process_time")
10
+
11
+ specify 'printer defaults to RubyProf::CallTreePrinter' do
12
+ profiler = Rack::Profiler.new(nil)
13
+ profiler.instance_variable_get('@printer').should.equal RubyProf::CallTreePrinter
14
+ profiler.instance_variable_get('@times').should.equal 1
15
+ end
16
+
17
+ specify 'CallTreePrinter has correct headers' do
18
+ headers = Rack::Profiler.new(app).call(request)[1]
19
+ headers.should.equal "Content-Disposition"=>"attachment; filename=\"/.process_time.tree\"", "Content-Type"=>"application/octet-stream"
20
+ end
21
+
22
+ specify 'FlatPrinter and GraphPrinter has Content-Type text/plain' do
23
+ %w(flat graph).each do |printer|
24
+ headers = Rack::Profiler.new(app, :printer => printer.to_sym).call(request)[1]
25
+ headers.should.equal "Content-Type"=>"text/plain"
26
+ end
27
+ end
28
+
29
+ specify 'GraphHtmlPrinter has Content-Type text/html' do
30
+ headers = Rack::Profiler.new(app, :printer => :graph_html).call(request)[1]
31
+ headers.should.equal "Content-Type"=>"text/html"
32
+ end
33
+ end
34
+
35
+ rescue LoadError => boom
36
+ $stderr.puts "WARN: Skipping Rack::Profiler tests (ruby-prof not installed)"
37
+ end