goliath 0.9.0

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

Potentially problematic release.


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

Files changed (84) hide show
  1. data/.gitignore +15 -0
  2. data/.rspec +2 -0
  3. data/.yardopts +2 -0
  4. data/Gemfile +3 -0
  5. data/LICENSE +66 -0
  6. data/README.md +86 -0
  7. data/Rakefile +18 -0
  8. data/examples/activerecord/config/srv.rb +7 -0
  9. data/examples/activerecord/srv.rb +37 -0
  10. data/examples/async_upload.rb +34 -0
  11. data/examples/conf_test.rb +27 -0
  12. data/examples/config/conf_test.rb +12 -0
  13. data/examples/config/echo.rb +1 -0
  14. data/examples/config/http_log.rb +7 -0
  15. data/examples/config/shared.rb +5 -0
  16. data/examples/custom_server.rb +57 -0
  17. data/examples/echo.rb +37 -0
  18. data/examples/gziped.rb +40 -0
  19. data/examples/hello_world.rb +10 -0
  20. data/examples/http_log.rb +85 -0
  21. data/examples/rack_routes.rb +44 -0
  22. data/examples/stream.rb +37 -0
  23. data/examples/valid.rb +19 -0
  24. data/goliath.gemspec +41 -0
  25. data/lib/goliath.rb +38 -0
  26. data/lib/goliath/api.rb +165 -0
  27. data/lib/goliath/application.rb +90 -0
  28. data/lib/goliath/connection.rb +94 -0
  29. data/lib/goliath/constants.rb +51 -0
  30. data/lib/goliath/env.rb +92 -0
  31. data/lib/goliath/goliath.rb +49 -0
  32. data/lib/goliath/headers.rb +37 -0
  33. data/lib/goliath/http_status_codes.rb +44 -0
  34. data/lib/goliath/plugins/latency.rb +33 -0
  35. data/lib/goliath/rack/default_mime_type.rb +30 -0
  36. data/lib/goliath/rack/default_response_format.rb +33 -0
  37. data/lib/goliath/rack/formatters/html.rb +90 -0
  38. data/lib/goliath/rack/formatters/json.rb +42 -0
  39. data/lib/goliath/rack/formatters/xml.rb +90 -0
  40. data/lib/goliath/rack/heartbeat.rb +23 -0
  41. data/lib/goliath/rack/jsonp.rb +38 -0
  42. data/lib/goliath/rack/params.rb +30 -0
  43. data/lib/goliath/rack/render.rb +66 -0
  44. data/lib/goliath/rack/tracer.rb +31 -0
  45. data/lib/goliath/rack/validation/boolean_value.rb +59 -0
  46. data/lib/goliath/rack/validation/default_params.rb +46 -0
  47. data/lib/goliath/rack/validation/numeric_range.rb +59 -0
  48. data/lib/goliath/rack/validation/request_method.rb +33 -0
  49. data/lib/goliath/rack/validation/required_param.rb +54 -0
  50. data/lib/goliath/rack/validation/required_value.rb +58 -0
  51. data/lib/goliath/rack/validation_error.rb +38 -0
  52. data/lib/goliath/request.rb +199 -0
  53. data/lib/goliath/response.rb +93 -0
  54. data/lib/goliath/runner.rb +236 -0
  55. data/lib/goliath/server.rb +149 -0
  56. data/lib/goliath/test_helper.rb +118 -0
  57. data/lib/goliath/version.rb +4 -0
  58. data/spec/integration/async_request_processing.rb +23 -0
  59. data/spec/integration/echo_spec.rb +27 -0
  60. data/spec/integration/keepalive_spec.rb +28 -0
  61. data/spec/integration/pipelining_spec.rb +43 -0
  62. data/spec/integration/valid_spec.rb +24 -0
  63. data/spec/spec_helper.rb +6 -0
  64. data/spec/unit/connection_spec.rb +59 -0
  65. data/spec/unit/env_spec.rb +55 -0
  66. data/spec/unit/headers_spec.rb +53 -0
  67. data/spec/unit/rack/default_mime_type_spec.rb +34 -0
  68. data/spec/unit/rack/formatters/json_spec.rb +54 -0
  69. data/spec/unit/rack/formatters/xml_spec.rb +66 -0
  70. data/spec/unit/rack/heartbeat_spec.rb +47 -0
  71. data/spec/unit/rack/params_spec.rb +94 -0
  72. data/spec/unit/rack/render_spec.rb +87 -0
  73. data/spec/unit/rack/validation/boolean_value_spec.rb +54 -0
  74. data/spec/unit/rack/validation/default_params_spec.rb +71 -0
  75. data/spec/unit/rack/validation/numeric_range_spec.rb +96 -0
  76. data/spec/unit/rack/validation/request_method_spec.rb +47 -0
  77. data/spec/unit/rack/validation/required_param_spec.rb +92 -0
  78. data/spec/unit/rack/validation/required_value_spec.rb +99 -0
  79. data/spec/unit/rack/validation_error_spec.rb +40 -0
  80. data/spec/unit/request_spec.rb +59 -0
  81. data/spec/unit/response_spec.rb +35 -0
  82. data/spec/unit/runner_spec.rb +129 -0
  83. data/spec/unit/server_spec.rb +137 -0
  84. metadata +409 -0
@@ -0,0 +1,96 @@
1
+ require 'spec_helper'
2
+ require 'goliath/rack/validation/numeric_range'
3
+
4
+ describe Goliath::Rack::Validation::NumericRange do
5
+ before(:each) do
6
+ @app = mock('app').as_null_object
7
+ @env = {'params' => {}}
8
+ end
9
+
10
+ it 'accepts options on create' do
11
+ opts = { :min => 1, :key => 2 }
12
+ lambda { Goliath::Rack::Validation::NumericRange.new('my app', opts) }.should_not raise_error(Exception)
13
+ end
14
+
15
+ describe 'with middleware' do
16
+ before(:each) do
17
+ @nr = Goliath::Rack::Validation::NumericRange.new(@app, {:key => 'id', :min => -5, :max => 20, :default => 15})
18
+ end
19
+
20
+ it 'uses the default if value is less then min' do
21
+ @env['params']['id'] = -10
22
+ @nr.call(@env)
23
+ @env['params']['id'].should == 15
24
+ end
25
+
26
+ it 'uses the default if value is greater then max' do
27
+ @env['params']['id'] = 25
28
+ @nr.call(@env)
29
+ @env['params']['id'].should == 15
30
+ end
31
+
32
+ it 'uses the first value, if the value is an array' do
33
+ @env['params']['id'] = [10,11,12]
34
+ @nr.call(@env)
35
+ @env['params']['id'].should == 10
36
+ end
37
+
38
+ it 'uses the default if value is not present' do
39
+ @nr.call(@env)
40
+ @env['params']['id'].should == 15
41
+ end
42
+
43
+ it 'uses the default if value is nil' do
44
+ @env['params']['id'] = nil
45
+ @nr.call(@env)
46
+ @env['params']['id'].should == 15
47
+ end
48
+
49
+ it 'returns the app status, headers and body' do
50
+ app_headers = {'Content-Type' => 'app'}
51
+ app_body = {'b' => 'c'}
52
+ @app.should_receive(:call).and_return([200, app_headers, app_body])
53
+
54
+ status, headers, body = @nr.call(@env)
55
+ status.should == 200
56
+ headers.should == app_headers
57
+ body.should == app_body
58
+ end
59
+ end
60
+
61
+ it 'raises error if key is not set' do
62
+ lambda { Goliath::Rack::Validation::NumericRange.new('app', {:min => 5}) }.should raise_error(Exception)
63
+ end
64
+
65
+ it 'raises error if neither min nor max set' do
66
+ lambda { Goliath::Rack::Validation::NumericRange.new('app', {:key => 5}) }.should raise_error(Exception)
67
+ end
68
+
69
+ it 'uses min if default not set' do
70
+ nr = Goliath::Rack::Validation::NumericRange.new(@app, {:key => 'id', :min => 5, :max => 10})
71
+ @env['params']['id'] = 15
72
+ nr.call(@env)
73
+ @env['params']['id'].should == 5
74
+ end
75
+
76
+ it 'uses max if default and min not set' do
77
+ nr = Goliath::Rack::Validation::NumericRange.new(@app, {:key => 'id', :max => 10})
78
+ @env['params']['id'] = 15
79
+ nr.call(@env)
80
+ @env['params']['id'].should == 10
81
+ end
82
+
83
+ it "doesn't require min" do
84
+ nr = Goliath::Rack::Validation::NumericRange.new(@app, {:key => 'id', :max => 10})
85
+ @env['params']['id'] = 8
86
+ nr.call(@env)
87
+ @env['params']['id'].should == 8
88
+ end
89
+
90
+ it "doesn't require max" do
91
+ nr = Goliath::Rack::Validation::NumericRange.new(@app, {:key => 'id', :min => 1})
92
+ @env['params']['id'] = 15
93
+ nr.call(@env)
94
+ @env['params']['id'].should == 15
95
+ end
96
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+ require 'goliath/rack/validation/request_method'
3
+
4
+ describe Goliath::Rack::Validation::RequestMethod do
5
+ before(:each) do
6
+ @app = mock('app').as_null_object
7
+ end
8
+
9
+ it 'accepts an app' do
10
+ lambda { Goliath::Rack::Validation::RequestMethod.new('my app') }.should_not raise_error(Exception)
11
+ end
12
+
13
+ describe 'with defaults' do
14
+ before(:each) do
15
+ @env = {}
16
+ @rm = Goliath::Rack::Validation::RequestMethod.new(@app, ['GET', 'POST'])
17
+ end
18
+
19
+ it 'raises error if method is invalid' do
20
+ @env['REQUEST_METHOD'] = 'fubar'
21
+ lambda { @rm.call(@env) }.should raise_error(Goliath::Validation::Error)
22
+ end
23
+
24
+ it 'allows valid methods through' do
25
+ @env['REQUEST_METHOD'] = 'GET'
26
+ lambda { @rm.call(@env) }.should_not raise_error
27
+ end
28
+
29
+ it 'returns app status, headers and body' do
30
+ app_headers = {'Content-Type' => 'asdf'}
31
+ app_body = {'a' => 'b'}
32
+ @app.should_receive(:call).and_return([200, app_headers, app_body])
33
+
34
+ @env['REQUEST_METHOD'] = 'POST'
35
+
36
+ status, headers, body = @rm.call(@env)
37
+ status.should == 200
38
+ headers.should == app_headers
39
+ body.should == app_body
40
+ end
41
+ end
42
+
43
+ it 'accepts methods on initialize' do
44
+ rm = Goliath::Rack::Validation::RequestMethod.new('my app', ['GET', 'DELETE', 'HEAD'])
45
+ rm.methods.should == ['GET', 'DELETE', 'HEAD']
46
+ end
47
+ end
@@ -0,0 +1,92 @@
1
+ require 'spec_helper'
2
+ require 'goliath/rack/validation/required_param'
3
+
4
+ describe Goliath::Rack::Validation::RequiredParam do
5
+ it 'accepts an app' do
6
+ lambda { Goliath::Rack::Validation::RequiredParam.new('my app') }.should_not raise_error(Exception)
7
+ end
8
+
9
+ it 'accepts options on create' do
10
+ opts = { :type => 1, :key => 2 }
11
+ lambda { Goliath::Rack::Validation::RequiredParam.new('my app', opts) }.should_not raise_error(Exception)
12
+ end
13
+
14
+ it 'defaults type and key' do
15
+ @rp = Goliath::Rack::Validation::RequiredParam.new('app')
16
+ @rp.key.should_not be_nil
17
+ @rp.key.should_not =~ /^\s*$/
18
+
19
+ @rp.type.should_not be_nil
20
+ @rp.type.should_not =~ /^\s*$/
21
+ end
22
+
23
+ describe 'with middleware' do
24
+ before(:each) do
25
+ @app = mock('app').as_null_object
26
+ @env = {'params' => {}}
27
+ @rp = Goliath::Rack::Validation::RequiredParam.new(@app, {:type => 'Monkey', :key => 'mk'})
28
+ end
29
+
30
+ it 'stores type and key options' do
31
+ @rp.type.should == 'Monkey'
32
+ @rp.key.should == 'mk'
33
+ end
34
+
35
+ it 'returns the app status, headers and body' do
36
+ app_headers = {'Content-Type' => 'app'}
37
+ app_body = {'b' => 'c'}
38
+ @app.should_receive(:call).and_return([201, app_headers, app_body])
39
+
40
+ @env['params']['mk'] = 'monkey'
41
+
42
+ status, headers, body = @rp.call(@env)
43
+ status.should == 201
44
+ headers.should == app_headers
45
+ body.should == app_body
46
+ end
47
+
48
+ describe 'key_valid!' do
49
+ it 'raises exception if the key is not provided' do
50
+ lambda { @rp.key_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
51
+ end
52
+
53
+ it 'raises exception if the key is blank' do
54
+ @env['params']['mk'] = ''
55
+
56
+ lambda { @rp.key_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
57
+ end
58
+
59
+ it 'raises exception if the key is nil' do
60
+ @env['params']['mk'] = nil
61
+
62
+ lambda { @rp.key_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
63
+ end
64
+
65
+ it 'handles an empty array' do
66
+ @env['params']['mk'] = []
67
+ lambda { @rp.key_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
68
+ end
69
+
70
+ it 'handles an array of nils' do
71
+ @env['params']['mk'] = [nil, nil, nil]
72
+ lambda { @rp.key_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
73
+ end
74
+
75
+ it 'handles an array of blanks' do
76
+ @env['params']['mk'] = ['', '', '']
77
+ lambda { @rp.key_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
78
+ end
79
+
80
+ it "doesn't raise if the key provided" do
81
+ @env['params']['mk'] = 'my value'
82
+
83
+ lambda { @rp.key_valid!(@env['params']) }.should_not raise_error(Goliath::Validation::Error)
84
+ end
85
+
86
+ it "doesn't raise if the array contains valid data" do
87
+ @env['params']['mk'] = [1, 2, 3, 4]
88
+ lambda{ @rp.key_valid!(@env['params']) }.should_not raise_error
89
+ end
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,99 @@
1
+ require 'spec_helper'
2
+ require 'goliath/rack/validation/required_value'
3
+
4
+ describe Goliath::Rack::Validation::RequiredValue do
5
+ it 'accepts an app' do
6
+ lambda { Goliath::Rack::Validation::RequiredValue.new('my app') }.should_not raise_error(Exception)
7
+ end
8
+
9
+ it 'accepts options on create' do
10
+ opts = { :key => 2, :values => ["foo", "bar"] }
11
+ lambda { Goliath::Rack::Validation::RequiredValue.new('my app', opts) }.should_not raise_error(Exception)
12
+ end
13
+
14
+
15
+ it 'turns a single option into an array' do
16
+ rv = Goliath::Rack::Validation::RequiredValue.new('my app', :key => 2, :values => "foo")
17
+ rv.values.should == ['foo']
18
+ end
19
+
20
+ describe 'with middleware' do
21
+ before(:each) do
22
+ @app = mock('app').as_null_object
23
+ @env = {'params' => {}}
24
+ @rv = Goliath::Rack::Validation::RequiredValue.new(@app, {:values => ['Monkey', 'frog'], :key => 'mk'})
25
+ end
26
+
27
+ it 'stores type and key options' do
28
+ @rv.values.should == ['Monkey', 'frog']
29
+ @rv.key.should == 'mk'
30
+ end
31
+
32
+ it 'returns the app status, headers and body' do
33
+ app_headers = {'Content-Type' => 'app'}
34
+ app_body = {'b' => 'c'}
35
+ @app.should_receive(:call).and_return([201, app_headers, app_body])
36
+
37
+ @env['params']['mk'] = 'Monkey'
38
+
39
+ status, headers, body = @rv.call(@env)
40
+ status.should == 201
41
+ headers.should == app_headers
42
+ body.should == app_body
43
+ end
44
+
45
+ context '#value_valid!' do
46
+ it 'raises exception if the key is not provided' do
47
+ lambda { @rv.value_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
48
+ end
49
+
50
+ it 'raises exception if the key is blank' do
51
+ @env['params']['mk'] = ''
52
+
53
+ lambda { @rv.value_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
54
+ end
55
+
56
+ it 'raises exception if the key is nil' do
57
+ @env['params']['mk'] = nil
58
+
59
+ lambda { @rv.value_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
60
+ end
61
+
62
+ it 'raises exception if the key is does not match' do
63
+ @env['params']['mk'] = "blarg"
64
+
65
+ lambda { @rv.value_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
66
+ end
67
+
68
+ it 'handles an empty array' do
69
+ @env['params']['mk'] = []
70
+ lambda { @rv.value_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
71
+ end
72
+
73
+ it 'handles an array of nils' do
74
+ @env['params']['mk'] = [nil, nil, nil]
75
+ lambda { @rv.value_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
76
+ end
77
+
78
+ it 'handles an array of blanks' do
79
+ @env['params']['mk'] = ['', '', '']
80
+ lambda { @rv.value_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
81
+ end
82
+
83
+ it "doesn't raise if the key is value" do
84
+ @env['params']['mk'] = 'Monkey'
85
+ lambda { @rv.value_valid!(@env['params']) }.should_not raise_error(Goliath::Validation::Error)
86
+ end
87
+
88
+ it "doesn't raise if the array contains valid data" do
89
+ @env['params']['mk'] = ['Monkey', 'frog']
90
+ lambda{ @rv.value_valid!(@env['params']) }.should_not raise_error
91
+ end
92
+
93
+ it 'raises if any of the array elements do not match' do
94
+ @env['params']['mk'] = ["Monkey", "frog", "bat"]
95
+ lambda { @rv.value_valid!(@env['params']) }.should raise_error(Goliath::Validation::Error)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+ require 'goliath/rack/validation_error'
3
+
4
+ describe Goliath::Rack::ValidationError do
5
+ it 'accepts an app' do
6
+ lambda { Goliath::Rack::ValidationError.new('my app') }.should_not raise_error(Exception)
7
+ end
8
+
9
+ describe 'with middleware' do
10
+ before(:each) do
11
+ @app = mock('app').as_null_object
12
+ @ve = Goliath::Rack::ValidationError.new(@app)
13
+ end
14
+
15
+ it 'returns the apps status' do
16
+ app_headers = {'Content-Type' => 'mine'}
17
+ app_body = {'a' => 'b'}
18
+ @app.should_receive(:call).and_return([200, app_headers, app_body])
19
+
20
+ status, headers, body = @ve.call({})
21
+ status.should == 200
22
+ headers.should == app_headers
23
+ body.should == app_body
24
+ end
25
+
26
+ it 'catches Goliath::Validation::Error' do
27
+ @app.should_receive(:call).and_raise(Goliath::Validation::Error.new(401, 'my error'))
28
+ lambda { @ve.call({}) }.should_not raise_error(Goliath::Validation::Error)
29
+ end
30
+
31
+ it 'returns an error response on exception' do
32
+ @app.should_receive(:call).and_raise(Goliath::Validation::Error.new(401, 'my error'))
33
+ status, headers, body = @ve.call({})
34
+
35
+ status.should == 401
36
+ headers.should == {}
37
+ body.should == {:error => 'my error'}
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ describe Goliath::Request do
4
+ before(:each) do
5
+
6
+ app = mock('app').as_null_object
7
+ env = Goliath::Env.new
8
+
9
+ @r = Goliath::Request.new(app, nil, env)
10
+ end
11
+
12
+ describe 'initialization' do
13
+
14
+ it 'initializes env defaults' do
15
+ env = Goliath::Env.new
16
+ env['INIT'] = 'init'
17
+
18
+ r = Goliath::Request.new(nil, nil, env)
19
+ r.env['INIT'].should == 'init'
20
+ end
21
+
22
+ it 'initializes an async callback' do
23
+ @r.env['async.callback'].should_not be_nil
24
+ end
25
+
26
+ it 'initializes request' do
27
+ @r.instance_variable_get("@state").should == :processing
28
+ end
29
+ end
30
+
31
+ describe 'process' do
32
+
33
+ it 'executes the application' do
34
+ app_mock = mock('app').as_null_object
35
+ env_mock = mock('app').as_null_object
36
+ request = Goliath::Request.new(app_mock, nil, env_mock)
37
+
38
+ app_mock.should_receive(:call).with(request.env)
39
+ request.should_receive(:post_process)
40
+
41
+ request.process
42
+ end
43
+
44
+ end
45
+
46
+ describe 'finished?' do
47
+ it "returns false if the request parsing has not yet finished" do
48
+ @r.finished?.should be_false
49
+ end
50
+
51
+ it 'returns true if we have finished request parsing' do
52
+ @r.should_receive(:post_process).and_return(nil)
53
+ @r.process
54
+
55
+ @r.finished?.should be_true
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,35 @@
1
+ require 'spec_helper'
2
+ require 'goliath/response'
3
+
4
+ describe Goliath::Response do
5
+ before(:each) do
6
+ @r = Goliath::Response.new
7
+ end
8
+
9
+ it 'allows setting status' do
10
+ @r.status = 400
11
+ @r.status.should == 400
12
+ end
13
+
14
+ it 'allows setting headers' do
15
+ @r.headers = [['my_key', 'my_headers']]
16
+ @r.headers.to_s.should == "my_key: my_headers\r\n"
17
+ end
18
+
19
+ it 'allows setting body' do
20
+ @r.body = 'my body'
21
+ @r.body.should == 'my body'
22
+ end
23
+
24
+ it 'sets a default status' do
25
+ @r.status.should == 200
26
+ end
27
+
28
+ it 'sets default headers' do
29
+ @r.headers.should_not be_nil
30
+ end
31
+
32
+ it 'outputs the http header' do
33
+ @r.head.should == "HTTP/1.1 200 OK\r\n"
34
+ end
35
+ end