tennpipes-base 3.6.6

Sign up to get free protection for your applications and to get access to all the features.
Files changed (101) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +20 -0
  3. data/README.rdoc +294 -0
  4. data/Rakefile +1 -0
  5. data/bin/tennpipes +8 -0
  6. data/lib/tennpipes-base.rb +196 -0
  7. data/lib/tennpipes-base/application.rb +175 -0
  8. data/lib/tennpipes-base/application/application_setup.rb +202 -0
  9. data/lib/tennpipes-base/application/authenticity_token.rb +25 -0
  10. data/lib/tennpipes-base/application/flash.rb +229 -0
  11. data/lib/tennpipes-base/application/params_protection.rb +129 -0
  12. data/lib/tennpipes-base/application/routing.rb +1002 -0
  13. data/lib/tennpipes-base/application/show_exceptions.rb +50 -0
  14. data/lib/tennpipes-base/caller.rb +53 -0
  15. data/lib/tennpipes-base/cli/adapter.rb +33 -0
  16. data/lib/tennpipes-base/cli/base.rb +105 -0
  17. data/lib/tennpipes-base/cli/console.rb +20 -0
  18. data/lib/tennpipes-base/cli/launcher.rb +103 -0
  19. data/lib/tennpipes-base/cli/rake.rb +50 -0
  20. data/lib/tennpipes-base/cli/rake_tasks.rb +72 -0
  21. data/lib/tennpipes-base/command.rb +38 -0
  22. data/lib/tennpipes-base/ext/sinatra.rb +29 -0
  23. data/lib/tennpipes-base/filter.rb +52 -0
  24. data/lib/tennpipes-base/images/404.png +0 -0
  25. data/lib/tennpipes-base/images/500.png +0 -0
  26. data/lib/tennpipes-base/loader.rb +202 -0
  27. data/lib/tennpipes-base/logger.rb +492 -0
  28. data/lib/tennpipes-base/module.rb +58 -0
  29. data/lib/tennpipes-base/mounter.rb +308 -0
  30. data/lib/tennpipes-base/path_router.rb +119 -0
  31. data/lib/tennpipes-base/path_router/compiler.rb +110 -0
  32. data/lib/tennpipes-base/path_router/error_handler.rb +8 -0
  33. data/lib/tennpipes-base/path_router/matcher.rb +123 -0
  34. data/lib/tennpipes-base/path_router/route.rb +169 -0
  35. data/lib/tennpipes-base/reloader.rb +309 -0
  36. data/lib/tennpipes-base/reloader/rack.rb +26 -0
  37. data/lib/tennpipes-base/reloader/storage.rb +55 -0
  38. data/lib/tennpipes-base/router.rb +98 -0
  39. data/lib/tennpipes-base/server.rb +119 -0
  40. data/lib/tennpipes-base/tasks.rb +21 -0
  41. data/lib/tennpipes-base/version.rb +20 -0
  42. data/lib/tennpipes-base/version.rb~ +20 -0
  43. data/test/fixtures/app_gem/Gemfile +4 -0
  44. data/test/fixtures/app_gem/app/app.rb +3 -0
  45. data/test/fixtures/app_gem/app_gem.gemspec +17 -0
  46. data/test/fixtures/app_gem/lib/app_gem.rb +7 -0
  47. data/test/fixtures/app_gem/lib/app_gem/version.rb +3 -0
  48. data/test/fixtures/apps/complex.rb +32 -0
  49. data/test/fixtures/apps/demo_app.rb +7 -0
  50. data/test/fixtures/apps/demo_demo.rb +7 -0
  51. data/test/fixtures/apps/demo_project/api/app.rb +7 -0
  52. data/test/fixtures/apps/demo_project/api/lib/api_lib.rb +3 -0
  53. data/test/fixtures/apps/demo_project/app.rb +7 -0
  54. data/test/fixtures/apps/external_apps/fake_lib.rb +1 -0
  55. data/test/fixtures/apps/external_apps/fake_root.rb +2 -0
  56. data/test/fixtures/apps/helpers/class_methods_helpers.rb +4 -0
  57. data/test/fixtures/apps/helpers/instance_methods_helpers.rb +4 -0
  58. data/test/fixtures/apps/helpers/support.rb +1 -0
  59. data/test/fixtures/apps/helpers/system_helpers.rb +8 -0
  60. data/test/fixtures/apps/kiq.rb +3 -0
  61. data/test/fixtures/apps/lib/myklass.rb +2 -0
  62. data/test/fixtures/apps/lib/myklass/mysubklass.rb +4 -0
  63. data/test/fixtures/apps/models/child.rb +2 -0
  64. data/test/fixtures/apps/models/parent.rb +5 -0
  65. data/test/fixtures/apps/mountable_apps/rack_apps.rb +15 -0
  66. data/test/fixtures/apps/mountable_apps/static.html +1 -0
  67. data/test/fixtures/apps/precompiled_app.rb +19 -0
  68. data/test/fixtures/apps/simple.rb +32 -0
  69. data/test/fixtures/apps/static.rb +10 -0
  70. data/test/fixtures/apps/system.rb +13 -0
  71. data/test/fixtures/apps/system_class_methods_demo.rb +7 -0
  72. data/test/fixtures/apps/system_instance_methods_demo.rb +7 -0
  73. data/test/fixtures/dependencies/a.rb +9 -0
  74. data/test/fixtures/dependencies/b.rb +4 -0
  75. data/test/fixtures/dependencies/c.rb +1 -0
  76. data/test/fixtures/dependencies/circular/e.rb +13 -0
  77. data/test/fixtures/dependencies/circular/f.rb +2 -0
  78. data/test/fixtures/dependencies/circular/g.rb +2 -0
  79. data/test/fixtures/dependencies/d.rb +4 -0
  80. data/test/fixtures/reloadable_apps/external/app/app.rb +6 -0
  81. data/test/fixtures/reloadable_apps/external/app/controllers/base.rb +6 -0
  82. data/test/fixtures/reloadable_apps/main/app.rb +10 -0
  83. data/test/helper.rb +30 -0
  84. data/test/test_application.rb +185 -0
  85. data/test/test_core.rb +93 -0
  86. data/test/test_csrf_protection.rb +208 -0
  87. data/test/test_dependencies.rb +57 -0
  88. data/test/test_filters.rb +389 -0
  89. data/test/test_flash.rb +168 -0
  90. data/test/test_locale.rb +21 -0
  91. data/test/test_logger.rb +295 -0
  92. data/test/test_mounter.rb +302 -0
  93. data/test/test_params_protection.rb +195 -0
  94. data/test/test_reloader_complex.rb +74 -0
  95. data/test/test_reloader_external.rb +21 -0
  96. data/test/test_reloader_simple.rb +101 -0
  97. data/test/test_reloader_system.rb +113 -0
  98. data/test/test_restful_routing.rb +33 -0
  99. data/test/test_router.rb +281 -0
  100. data/test/test_routing.rb +2328 -0
  101. metadata +301 -0
@@ -0,0 +1,74 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/complex')
3
+
4
+ describe "ComplexReloader" do
5
+
6
+ describe 'for complex reload functionality' do
7
+ before do
8
+ Tennpipes.clear!
9
+ Tennpipes.mount("complex_1_demo").to("/complex_1_demo")
10
+ Tennpipes.mount("complex_2_demo").to("/complex_2_demo")
11
+ end
12
+
13
+ it 'should correctly instantiate Complex(1-2)Demo fixture' do
14
+ assert_equal ["/complex_1_demo", "/complex_2_demo"], Tennpipes.mounted_apps.map(&:uri_root)
15
+ assert_equal ["complex_1_demo", "complex_2_demo"], Tennpipes.mounted_apps.map(&:name)
16
+ assert Complex1Demo.reload?
17
+ assert Complex2Demo.reload?
18
+ assert_match %r{fixtures/apps/complex.rb}, Complex1Demo.app_file
19
+ assert_match %r{fixtures/apps/complex.rb}, Complex2Demo.app_file
20
+ end
21
+
22
+ it 'should correctly reload Complex(1-2)Demo fixture' do
23
+ assert_match %r{fixtures/apps/complex.rb}, Complex1Demo.app_file
24
+ @app = Tennpipes.application
25
+
26
+ get "/"
27
+ assert_equal 404, status
28
+
29
+ get "/complex_1_demo"
30
+ assert_equal "Given random #{LibDemo.give_me_a_random}", body
31
+
32
+ get "/complex_2_demo"
33
+ assert_equal 200, status
34
+
35
+ get "/complex_1_demo/old"
36
+ assert_equal 200, status
37
+
38
+ get "/complex_2_demo/old"
39
+ assert_equal 200, status
40
+
41
+ get "/complex_2_demo/var/destroy"
42
+ assert_equal '{}', body
43
+
44
+ new_phrase = "The magick number is: #{rand(2**255)}!"
45
+ buffer = File.read(Complex1Demo.app_file)
46
+ new_buffer = buffer.sub(/The magick number is: \d+!/, new_phrase)
47
+ new_buffer.sub!(/get\(:destroy\)/, 'get(:destroy, :with => :id)')
48
+ begin
49
+ File.open(Complex1Demo.app_file, "w") { |f| f.write(new_buffer) }
50
+ Time.stub(:now, Time.now + 2) { get "/complex_2_demo" }
51
+ assert_equal new_phrase, body
52
+
53
+ # Re-Check that we didn't forget any route
54
+ get "/complex_1_demo"
55
+ assert_equal "Given random #{LibDemo.give_me_a_random}", body
56
+
57
+ get "/complex_2_demo"
58
+ assert_equal 200, status
59
+
60
+ get "/complex_1_demo/old"
61
+ assert_equal 200, status
62
+
63
+ get "/complex_2_demo/old"
64
+ assert_equal 200, status
65
+
66
+ get "/complex_2_demo/var/destroy/variable"
67
+ assert_equal '{"id"=>"variable"}', body
68
+ ensure
69
+ # Now we need to prevent to commit a new changed file so we revert it
70
+ File.open(Complex1Demo.app_file, "w") { |f| f.write(buffer) }
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,21 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/reloadable_apps/main/app')
3
+
4
+ describe "ExternalReloader" do
5
+ describe "for external app" do
6
+ before do
7
+ Tennpipes.clear!
8
+ Tennpipes.mount("ReloadableApp::External").to("/reloadable/external")
9
+ Tennpipes.mount("ReloadableApp::Main").to("/reloadable")
10
+ Tennpipes.load!
11
+ end
12
+
13
+ it "should avoid reloading the file if its path is not started with Tennpipes.root" do
14
+ @app = Tennpipes.application
15
+ Tennpipes.stub(:root, File.expand_path(File.dirname(__FILE__) + '/fixtures/reloadable_apps/main')) do
16
+ get "/reloadable/external/base"
17
+ end
18
+ assert_equal "Hello External App", body
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,101 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/simple')
3
+
4
+ describe "SimpleReloader" do
5
+
6
+ describe 'for simple reset functionality' do
7
+
8
+ it 'should reset routes' do
9
+ mock_app do
10
+ (1..10).each do |i|
11
+ get("/#{i}") { "Foo #{i}" }
12
+ end
13
+ end
14
+ (1..10).each do |i|
15
+ get "/#{i}"
16
+ assert_equal "Foo #{i}", body
17
+ end
18
+ @app.reset_routes!
19
+ (1..10).each do |i|
20
+ get "/#{i}"
21
+ assert_equal 404, status
22
+ end
23
+ end
24
+
25
+ it 'should keep sinatra routes on development' do
26
+ mock_app do
27
+ set :environment, :development
28
+ get("/"){ "ok" }
29
+ end
30
+ assert_equal :development, @app.environment
31
+ get "/"
32
+ assert_equal 200, status
33
+ get "/__sinatra__/404.png"
34
+ assert_equal 200, status
35
+ assert_match /image\/png/, response["Content-Type"]
36
+ @app.reset_routes!
37
+ get "/"
38
+ assert_equal 404, status
39
+ get "/__sinatra__/404.png"
40
+ assert_equal 200, status
41
+ assert_match /image\/png/, response["Content-Type"]
42
+ end
43
+ end
44
+
45
+ describe 'for simple reload functionality' do
46
+ before do
47
+ Tennpipes.clear!
48
+ Tennpipes.mount("simple_demo").to("/")
49
+ Tennpipes.reload!
50
+ end
51
+
52
+ it 'should correctly instantiate SimpleDemo fixture' do
53
+ assert_equal ["simple_demo"], Tennpipes.mounted_apps.map(&:name)
54
+ assert SimpleDemo.reload?
55
+ assert_match %r{fixtures/apps/simple.rb}, SimpleDemo.app_file
56
+ end
57
+
58
+ it 'should correctly reload SimpleDemo fixture' do
59
+ @app = SimpleDemo
60
+ get "/"
61
+ assert ok?
62
+ new_phrase = "The magick number is: #{rand(2**255)}!"
63
+ buffer = File.read(SimpleDemo.app_file)
64
+ new_buffer = buffer.sub(/The magick number is: \d+!/, new_phrase)
65
+ begin
66
+ File.open(SimpleDemo.app_file, "w") { |f| f.write(new_buffer) }
67
+ Time.stub(:now, Time.now + 2) { get "/" }
68
+ assert_equal new_phrase, body
69
+ ensure
70
+ File.open(SimpleDemo.app_file, "w") { |f| f.write(buffer) }
71
+ Tennpipes.reload!
72
+ end
73
+ end
74
+
75
+ it 'should correctly reset SimpleDemo fixture' do
76
+ @app = SimpleDemo
77
+ get "/"
78
+ @app.reload!
79
+ get "/rand"
80
+ assert ok?
81
+ last_body = body
82
+ assert_equal 1, @app.filters[:before].size
83
+ assert_equal 1, @app.errors.size
84
+ assert_equal 2, @app.filters[:after].size # app + content-type + tennpipes-flash
85
+ assert_equal 0, @app.middleware.size
86
+ assert_equal 4, @app.routes.size # GET+HEAD of "/" + GET+HEAD of "/rand" = 4
87
+ assert_equal 4, @app.extensions.size # [Tennpipes::ApplicationSetup, Tennpipes::ParamsProtection, Tennpipes::Routing, Tennpipes::Flash]
88
+ assert_equal 0, @app.templates.size
89
+ @app.reload!
90
+ get "/rand"
91
+ refute_equal last_body, body
92
+ assert_equal 1, @app.filters[:before].size
93
+ assert_equal 1, @app.errors.size
94
+ assert_equal 2, @app.filters[:after].size
95
+ assert_equal 0, @app.middleware.size
96
+ assert_equal 4, @app.routes.size # GET+HEAD of "/" = 2
97
+ assert_equal 4, @app.extensions.size # [Tennpipes::ApplicationSetup, Tennpipes::ParamsProtection, Tennpipes::Routing, Tennpipes::Flash]
98
+ assert_equal 0, @app.templates.size
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,113 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/kiq')
3
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/system')
4
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/static')
5
+
6
+ describe "SystemReloader" do
7
+ describe 'for wierd and difficult reload events' do
8
+ before do
9
+ @app = SystemDemo
10
+ get '/'
11
+ end
12
+
13
+ it 'should reload system features if they were required only in helper' do
14
+ @app.reload!
15
+ get '/'
16
+ assert_equal 'Resolv', body
17
+ end
18
+
19
+ it 'should reload children on parent change' do
20
+ Tennpipes.mount(SystemDemo).to("/")
21
+ assert_equal Child.new.family, 'Danes'
22
+ parent_file = File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/models/parent.rb')
23
+ new_class = <<-DOC
24
+ class Parent
25
+ def family
26
+ 'Dancy'
27
+ end
28
+ def shmamily
29
+ 'Shmancy'
30
+ end
31
+ end
32
+ DOC
33
+ begin
34
+ backup = File.read(parent_file)
35
+ Tennpipes::Reloader.reload!
36
+ assert_equal 'Danes', Parent.new.family
37
+ assert_equal 'Danes', Child.new.family
38
+ File.open(parent_file, "w") { |f| f.write(new_class) }
39
+ Tennpipes::Reloader.reload!
40
+ assert_equal 'Dancy', Parent.new.family
41
+ assert_equal 'Shmancy', Parent.new.shmamily
42
+ assert_equal 'Dancy', Child.new.family
43
+ assert_equal 'Shmancy', Child.new.shmamily
44
+ ensure
45
+ File.open(parent_file, "w") { |f| f.write(backup) }
46
+ end
47
+ end
48
+
49
+ it 'should not fail horribly on reload event with non-tennpipes apps' do
50
+ Tennpipes.mount("kiq").to("/")
51
+ Tennpipes.reload!
52
+ end
53
+
54
+ it 'should not reload apps with disabled reload' do
55
+ Tennpipes.mount(StaticDemo).to("/")
56
+ Tennpipes.reload!
57
+ end
58
+ end
59
+
60
+ describe 'reloading external constants' do
61
+ it 'should not touch external constants defining singleton methods' do
62
+ new_class = <<-DOC
63
+ class SingletonClassTest
64
+ def self.external_test
65
+ end
66
+ end
67
+ DOC
68
+ tmp_file = '/tmp/tennpipes_class_demo.rb'
69
+ begin
70
+ File.open(tmp_file, "w") { |f| f.write(new_class) }
71
+ Tennpipes.clear!
72
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/system_class_methods_demo.rb')
73
+ @app = SystemClassMethodsDemo
74
+ Tennpipes.mount(SystemClassMethodsDemo).to("/")
75
+ get '/'
76
+ assert defined?(SingletonClassTest), 'SingletonClassTest undefined'
77
+ assert_includes SingletonClassTest.singleton_methods, :external_test
78
+ FileUtils.touch File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/helpers/class_methods_helpers.rb')
79
+ Tennpipes.reload!
80
+ assert defined?(SingletonClassTest), 'SingletonClassTest undefined'
81
+ assert_includes SingletonClassTest.singleton_methods, :external_test
82
+ ensure
83
+ FileUtils.rm tmp_file
84
+ end
85
+ end
86
+
87
+ it 'should not touch external constants defining instance methods' do
88
+ new_class = <<-DOC
89
+ class InstanceTest
90
+ def instance_test
91
+ end
92
+ end
93
+ DOC
94
+ tmp_file = '/tmp/tennpipes_instance_demo.rb'
95
+ begin
96
+ File.open(tmp_file, "w") { |f| f.write(new_class) }
97
+ Tennpipes.clear!
98
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/system_instance_methods_demo.rb')
99
+ @app = SystemInstanceMethodsDemo
100
+ Tennpipes.mount(SystemInstanceMethodsDemo).to("/")
101
+ get '/'
102
+ assert defined?(InstanceTest), 'InstanceTest undefined'
103
+ assert_includes InstanceTest.new.methods, :instance_test
104
+ FileUtils.touch File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/helpers/instance_methods_helpers.rb')
105
+ Tennpipes.reload!
106
+ assert defined?(InstanceTest), 'InstanceTest undefined'
107
+ assert_includes InstanceTest.new.methods, :instance_test
108
+ ensure
109
+ FileUtils.rm tmp_file
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,33 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+
3
+ describe "Routing" do
4
+ it 'should perform restul routing' do
5
+ mock_app do
6
+ controller :parent => :parents do
7
+ get :index, :with => :asset_id do
8
+ "#{url_for(:index, params[:parent_id], :asset_id => params[:asset_id])} get"
9
+ end
10
+
11
+ put :index, :with => :asset_id do
12
+ "#{url_for(:index, params[:parent_id], :asset_id => params[:asset_id])} put"
13
+ end
14
+
15
+ post :index, :with => :asset_id do
16
+ "#{url_for(:index, :parent_id => params[:parent_id], :asset_id => params[:asset_id])} post"
17
+ end
18
+
19
+ delete :index, :with => :asset_id do
20
+ "#{url_for(:index, params[:parent_id], :asset_id => params[:asset_id])} delete"
21
+ end
22
+ end
23
+ end
24
+ get "/parents/1/hi"
25
+ assert_equal "/parents/1/hi get", body
26
+ put "/parents/1/hi"
27
+ assert_equal "/parents/1/hi put", body
28
+ post "/parents/1/hi"
29
+ assert_equal "/parents/1/hi post", body
30
+ delete "/parents/1/hi"
31
+ assert_equal "/parents/1/hi delete", body
32
+ end
33
+ end
@@ -0,0 +1,281 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/fixtures/apps/simple')
3
+
4
+ describe "Router" do
5
+
6
+ def setup
7
+ Tennpipes.clear!
8
+ end
9
+
10
+ it 'should dispatch paths correctly' do
11
+ app = lambda { |env|
12
+ [200, {
13
+ 'X-ScriptName' => env['SCRIPT_NAME'],
14
+ 'X-PathInfo' => env['PATH_INFO'],
15
+ 'Content-Type' => 'text/plain'
16
+ }, [""]]
17
+ }
18
+ map = Tennpipes::Router.new(
19
+ { :path => '/bar', :to => app },
20
+ { :path => '/foo/bar', :to => app },
21
+ { :path => '/foo', :to => app }
22
+ )
23
+
24
+ res = Rack::MockRequest.new(map).get("/")
25
+ assert res.not_found?
26
+
27
+ res = Rack::MockRequest.new(map).get("/qux")
28
+ assert res.not_found?
29
+
30
+ res = Rack::MockRequest.new(map).get("/foo")
31
+ assert res.ok?
32
+ assert_equal "/foo", res["X-ScriptName"]
33
+ assert_equal "/", res["X-PathInfo"]
34
+
35
+ res = Rack::MockRequest.new(map).get("/foo/")
36
+ assert res.ok?
37
+ assert_equal "/foo", res["X-ScriptName"]
38
+ assert_equal "/", res["X-PathInfo"]
39
+
40
+ res = Rack::MockRequest.new(map).get("/foo/bar")
41
+ assert res.ok?
42
+ assert_equal "/foo/bar", res["X-ScriptName"]
43
+ assert_equal "/", res["X-PathInfo"]
44
+
45
+ res = Rack::MockRequest.new(map).get("/foo/bar/")
46
+ assert res.ok?
47
+ assert_equal "/foo/bar", res["X-ScriptName"]
48
+ assert_equal "/", res["X-PathInfo"]
49
+
50
+ res = Rack::MockRequest.new(map).get("/foo///bar//quux")
51
+ assert_equal 200, res.status
52
+ assert res.ok?
53
+ assert_equal "/foo/bar", res["X-ScriptName"]
54
+ assert_equal "//quux", res["X-PathInfo"]
55
+
56
+ res = Rack::MockRequest.new(map).get("/foo/quux", "SCRIPT_NAME" => "/bleh")
57
+ assert res.ok?
58
+ assert_equal "/bleh/foo", res["X-ScriptName"]
59
+ assert_equal "/quux", res["X-PathInfo"]
60
+
61
+ res = Rack::MockRequest.new(map).get("/bar", 'HTTP_HOST' => 'foo.org')
62
+ assert res.ok?
63
+ assert_equal "/bar", res["X-ScriptName"]
64
+ assert_equal "/", res["X-PathInfo"]
65
+
66
+ res = Rack::MockRequest.new(map).get("/bar/", 'HTTP_HOST' => 'foo.org')
67
+ assert res.ok?
68
+ assert_equal "/bar", res["X-ScriptName"]
69
+ assert_equal "/", res["X-PathInfo"]
70
+ end
71
+
72
+ it 'should dispatch requests to cascade mounted apps' do
73
+ app = lambda { |env|
74
+ scary = !!env['PATH_INFO'].match(/scary/)
75
+ [scary ? 404 : 200, {
76
+ 'X-ScriptName' => env['SCRIPT_NAME'],
77
+ 'X-PathInfo' => env['PATH_INFO'],
78
+ 'Content-Type' => 'text/plain'
79
+ }, [""]]
80
+ }
81
+ api = lambda { |env|
82
+ spooky = !!env['QUERY_STRING'].match(/spooky/)
83
+ [spooky ? 200 : 404, {
84
+ 'X-API' => spooky,
85
+ 'X-ScriptName' => env['SCRIPT_NAME'],
86
+ 'X-PathInfo' => env['PATH_INFO'],
87
+ 'Content-Type' => 'application/json'
88
+ }, [""]]
89
+ }
90
+ map = Tennpipes::Router.new(
91
+ { :path => '/bar', :to => api },
92
+ { :path => '/bar', :to => app }
93
+ )
94
+
95
+ res = Rack::MockRequest.new(map).get("/werewolf")
96
+ assert_equal 404, res.status
97
+ assert_equal nil, res["X-API"]
98
+ assert_equal nil, res["X-ScriptName"]
99
+ assert_equal nil, res["X-PathInfo"]
100
+
101
+ res = Rack::MockRequest.new(map).get("/bar/mitzvah")
102
+ assert res.ok?
103
+ assert_equal nil, res["X-API"]
104
+ assert_equal 'text/plain', res["Content-Type"]
105
+ assert_equal "/bar", res["X-ScriptName"]
106
+ assert_equal "/mitzvah", res["X-PathInfo"]
107
+
108
+ res = Rack::MockRequest.new(map).get("/bar?spooky")
109
+ assert res.ok?
110
+ assert_equal true, res["X-API"]
111
+ assert_equal 'application/json', res["Content-Type"]
112
+ assert_equal "/bar", res["X-ScriptName"]
113
+ assert_equal "/", res["X-PathInfo"]
114
+
115
+ res = Rack::MockRequest.new(map).get("/bar/scary")
116
+ assert_equal 404, res.status
117
+ assert_equal nil, res["X-API"]
118
+ assert_equal 'text/plain', res["Content-Type"]
119
+ assert_equal "/bar", res["X-ScriptName"]
120
+ assert_equal "/scary", res["X-PathInfo"]
121
+ end
122
+
123
+ it 'should dispatch requests to cascade mounted apps and not cascade ok statuses' do
124
+
125
+ api = mock_app do
126
+ get 'scary' do
127
+ "1"
128
+ end
129
+ set :cascade, true
130
+ end
131
+
132
+ app = mock_app do
133
+ get 'scary' do
134
+ "2"
135
+ end
136
+ set :cascade, false
137
+ end
138
+
139
+ app2 = mock_app do
140
+ get 'terrifying' do
141
+ ""
142
+ end
143
+ end
144
+
145
+ map = Tennpipes::Router.new(
146
+ { :path => '/bar', :to => api },
147
+ { :path => '/bar', :to => app },
148
+ { :path => '/bar', :to => app2 }
149
+ )
150
+
151
+ res = Rack::MockRequest.new(map).get("/bar/scary")
152
+ assert res.ok?
153
+ #asserting that on ok we're good to go
154
+ assert_equal "1", res.body
155
+
156
+ res = Rack::MockRequest.new(map).get("/bar/terrifying")
157
+ assert !res.ok?
158
+
159
+ end
160
+
161
+ it 'should dispatch requests to cascade mounted apps until it sees a cascade == false or []g' do
162
+ app = mock_app do
163
+ get 'scary' do
164
+ ""
165
+ end
166
+ set :cascade, []
167
+ end
168
+
169
+ app2 = mock_app do
170
+ get 'terrifying' do
171
+ ""
172
+ end
173
+ end
174
+
175
+ map = Tennpipes::Router.new(
176
+ { :path => '/bar', :to => app },
177
+ { :path => '/bar', :to => app2 }
178
+ )
179
+
180
+ request_case = lambda {
181
+ Rack::MockRequest.new(map).get("/bar/terrifying")
182
+ }
183
+
184
+ app.cascade = false
185
+ assert !request_case.call.ok?
186
+
187
+ app.cascade = true
188
+ assert request_case.call.ok?
189
+ end
190
+
191
+ it 'should dispatches hosts correctly' do
192
+ map = Tennpipes::Router.new(
193
+ { :host => "foo.org", :to => lambda { |env|
194
+ [200,
195
+ { "Content-Type" => "text/plain",
196
+ "X-Position" => "foo.org",
197
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
198
+ }, [""]]}},
199
+ { :host => "subdomain.foo.org", :to => lambda { |env|
200
+ [200,
201
+ { "Content-Type" => "text/plain",
202
+ "X-Position" => "subdomain.foo.org",
203
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
204
+ }, [""]]}},
205
+ { :host => /.*\.bar.org/, :to => lambda { |env|
206
+ [200,
207
+ { "Content-Type" => "text/plain",
208
+ "X-Position" => "bar.org",
209
+ "X-Host" => env["HTTP_HOST"] || env["SERVER_NAME"],
210
+ }, [""]]}}
211
+ )
212
+
213
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "bar.org")
214
+ assert res.not_found?
215
+
216
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "at.bar.org")
217
+ assert res.ok?
218
+ assert_equal "bar.org", res["X-Position"]
219
+
220
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "foo.org")
221
+ assert res.ok?
222
+ assert_equal "foo.org", res["X-Position"]
223
+
224
+ res = Rack::MockRequest.new(map).get("/", "HTTP_HOST" => "subdomain.foo.org", "SERVER_NAME" => "foo.org")
225
+ assert res.ok?
226
+ assert_equal "subdomain.foo.org", res["X-Position"]
227
+ end
228
+
229
+ it 'should works with tennpipes core applications' do
230
+ Tennpipes.mount("simple_demo").host("tennpipes.org")
231
+ assert_equal ["simple_demo"], Tennpipes.mounted_apps.map(&:name)
232
+ assert_equal ["tennpipes.org"], Tennpipes.mounted_apps.map(&:app_host)
233
+
234
+ res = Rack::MockRequest.new(Tennpipes.application).get("/")
235
+ assert res.not_found?
236
+
237
+ res = Rack::MockRequest.new(Tennpipes.application).get("/", "HTTP_HOST" => "bar.org")
238
+ assert res.not_found?
239
+
240
+ res = Rack::MockRequest.new(Tennpipes.application).get("/", "HTTP_HOST" => "tennpipes.org")
241
+ assert res.ok?
242
+ end
243
+
244
+ it 'should works with tennpipes applications' do
245
+ Tennpipes.mount("simple_demo").to("/foo").host(/.*\.tennpipes.org/)
246
+
247
+ res = Rack::MockRequest.new(Tennpipes.application).get("/")
248
+ assert res.not_found?
249
+
250
+ res = Rack::MockRequest.new(Tennpipes.application).get("/", "HTTP_HOST" => "bar.org")
251
+ assert res.not_found?
252
+
253
+ res = Rack::MockRequest.new(Tennpipes.application).get("/", "HTTP_HOST" => "tennpipes.org")
254
+ assert res.not_found?
255
+
256
+ res = Rack::MockRequest.new(Tennpipes.application).get("/none", "HTTP_HOST" => "foo.tennpipes.org")
257
+ assert res.not_found?
258
+
259
+ res = Rack::MockRequest.new(Tennpipes.application).get("/foo", "HTTP_HOST" => "bar.tennpipes.org")
260
+ assert res.ok?
261
+
262
+ res = Rack::MockRequest.new(Tennpipes.application).get("/foo/", "HTTP_HOST" => "bar.tennpipes.org")
263
+ assert res.ok?
264
+ end
265
+
266
+ it 'should keep the same environment object' do
267
+ app = lambda { |env|
268
+ env['path'] = env['PATH_INFO']
269
+ [200, {'Content-Type' => 'text/plain'}, [""]]
270
+ }
271
+ map = Tennpipes::Router.new(
272
+ { :path => '/bar', :to => app },
273
+ { :path => '/foo/bar', :to => app },
274
+ { :path => '/foo', :to => app }
275
+ )
276
+
277
+ env = Rack::MockRequest.env_for("/bar/foo")
278
+ map.call(env)
279
+ assert_equal "/foo", env["path"]
280
+ end
281
+ end