goliath 0.9.4 → 1.0.0.beta.1

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 (102) hide show
  1. data/.gitignore +3 -0
  2. data/Guardfile +8 -0
  3. data/HISTORY.md +10 -0
  4. data/LICENSE +1 -1
  5. data/README.md +28 -29
  6. data/Rakefile +10 -2
  7. data/examples/activerecord/config/srv.rb +2 -1
  8. data/examples/activerecord/srv.rb +14 -5
  9. data/examples/api_proxy.rb +3 -7
  10. data/examples/around.rb +38 -0
  11. data/examples/async_aroundware_demo.rb +2 -2
  12. data/examples/async_upload.rb +1 -1
  13. data/examples/auth_and_rate_limit.rb +1 -1
  14. data/examples/clone.rb +26 -0
  15. data/examples/config/websocket.rb +1 -0
  16. data/examples/custom_logs.rb +21 -0
  17. data/examples/custom_server.rb +6 -44
  18. data/examples/early_abort.rb +6 -3
  19. data/examples/echo.rb +1 -1
  20. data/examples/fiber_pool.rb +35 -0
  21. data/examples/grape/config/apiserver.rb +8 -0
  22. data/examples/grape/server.rb +67 -0
  23. data/examples/gziped.rb +1 -1
  24. data/examples/params.rb +36 -0
  25. data/examples/rasterize/rasterize.rb +1 -2
  26. data/examples/router.rb +15 -0
  27. data/examples/template.rb +14 -7
  28. data/examples/test.rb +31 -0
  29. data/examples/upload.rb +17 -0
  30. data/examples/views/joke.markdown +4 -4
  31. data/examples/websocket.rb +39 -0
  32. data/examples/ws/favicon.ico +0 -0
  33. data/examples/ws/index.erb +50 -0
  34. data/goliath.gemspec +24 -6
  35. data/lib/goliath/api.rb +15 -82
  36. data/lib/goliath/application.rb +3 -17
  37. data/lib/goliath/connection.rb +16 -9
  38. data/lib/goliath/constants.rb +2 -0
  39. data/lib/goliath/env.rb +2 -3
  40. data/lib/goliath/goliath.rb +24 -34
  41. data/lib/goliath/plugins/latency.rb +7 -3
  42. data/lib/goliath/rack/builder.rb +1 -37
  43. data/lib/goliath/rack/favicon.rb +31 -0
  44. data/lib/goliath/rack/formatters/json.rb +1 -1
  45. data/lib/goliath/rack/heartbeat.rb +1 -0
  46. data/lib/goliath/rack/jsonp.rb +1 -0
  47. data/lib/goliath/rack/params.rb +2 -17
  48. data/lib/goliath/rack/render.rb +0 -1
  49. data/lib/goliath/rack/templates.rb +18 -7
  50. data/lib/goliath/rack/types/base.rb +24 -0
  51. data/lib/goliath/rack/types/boolean.rb +18 -0
  52. data/lib/goliath/rack/types/core.rb +19 -0
  53. data/lib/goliath/rack/types/symbol.rb +16 -0
  54. data/lib/goliath/rack/types.rb +10 -0
  55. data/lib/goliath/rack/validation/coerce.rb +48 -0
  56. data/lib/goliath/rack/validation/param.rb +113 -0
  57. data/lib/goliath/rack/validation/request_method.rb +1 -1
  58. data/lib/goliath/rack/validation/required.rb +47 -0
  59. data/lib/goliath/rack/validation/required_param.rb +42 -17
  60. data/lib/goliath/rack/validation.rb +3 -0
  61. data/lib/goliath/rack.rb +2 -2
  62. data/lib/goliath/request.rb +41 -9
  63. data/lib/goliath/response.rb +0 -2
  64. data/lib/goliath/runner.rb +55 -4
  65. data/lib/goliath/server.rb +7 -3
  66. data/lib/goliath/test_helper.rb +70 -16
  67. data/lib/goliath/test_helper_ws.rb +42 -0
  68. data/lib/goliath/version.rb +1 -1
  69. data/lib/goliath/websocket.rb +80 -0
  70. data/pkg/goliath-0.9.4.gem +0 -0
  71. data/pkg/goliath-1.0.0.beta.1.gem +0 -0
  72. data/spec/integration/async_request_processing.rb +1 -1
  73. data/spec/integration/early_abort_spec.rb +3 -10
  74. data/spec/integration/echo_spec.rb +8 -8
  75. data/spec/integration/jsonp_spec.rb +31 -0
  76. data/spec/integration/keepalive_spec.rb +2 -2
  77. data/spec/integration/template_spec.rb +10 -5
  78. data/spec/integration/test_helper_spec.rb +33 -0
  79. data/spec/integration/valid_spec.rb +35 -5
  80. data/spec/integration/websocket_spec.rb +44 -0
  81. data/spec/unit/api_spec.rb +2 -19
  82. data/spec/unit/connection_spec.rb +3 -0
  83. data/spec/unit/rack/formatters/json_spec.rb +3 -3
  84. data/spec/unit/rack/heartbeat_spec.rb +13 -0
  85. data/spec/unit/rack/params_spec.rb +2 -8
  86. data/spec/unit/rack/validation/param_spec.rb +443 -0
  87. data/spec/unit/rack/validation/request_method_spec.rb +5 -0
  88. data/spec/unit/rack/validation/required_param_spec.rb +71 -1
  89. data/spec/unit/runner_spec.rb +21 -7
  90. data/test/echo_test.rb +25 -0
  91. data/test/test_helper.rb +5 -0
  92. metadata +316 -78
  93. data/examples/env_use_statements.rb +0 -20
  94. data/examples/favicon.rb +0 -40
  95. data/examples/rack_routes.rb +0 -125
  96. data/examples/rasterize/thumb/f7ad4cb03e5bfd0e2c43db8e598fb3cd.png +0 -0
  97. data/examples/valid.rb +0 -17
  98. data/lib/goliath/deprecated/async_aroundware.rb +0 -133
  99. data/lib/goliath/deprecated/mongo_receiver.rb +0 -84
  100. data/lib/goliath/deprecated/response_receiver.rb +0 -97
  101. data/spec/integration/rack_routes_spec.rb +0 -169
  102. data/spec/unit/rack/builder_spec.rb +0 -40
@@ -9,13 +9,13 @@ describe 'HTTP Keep-Alive support' do
9
9
 
10
10
  r1.errback { fail }
11
11
  r1.callback do |c|
12
- b = Yajl::Parser.parse(c.response)
12
+ b = MultiJson.load(c.response)
13
13
  b['response'].should == 'test'
14
14
 
15
15
  r2 = conn.get(:query => {:echo => 'test2'})
16
16
  r2.errback { fail }
17
17
  r2.callback do |c|
18
- b = Yajl::Parser.parse(c.response)
18
+ b = MultiJson.load(c.response)
19
19
  b['response'].should == 'test2'
20
20
 
21
21
  stop
@@ -1,9 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require File.join(File.dirname(__FILE__), '../../', 'examples/template')
3
3
 
4
-
5
4
  describe Template do
6
-
7
5
  def config_file
8
6
  File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'examples', 'config', 'template.rb'))
9
7
  end
@@ -11,18 +9,25 @@ describe Template do
11
9
  let(:api_options) { { :config => config_file } }
12
10
 
13
11
  it 'renders haml template with default haml layout' do
14
-
15
12
  with_api(Template, api_options) do
16
- get_request do |c|
13
+ get_request(:path => '/root') do |c|
17
14
  c.response.should =~ %r{<li><a href="/joke">Tell me a joke</a></li>}
18
15
  end
19
16
  end
20
17
  end
21
18
 
19
+ it 'renders haml template from string with default haml layout' do
20
+ with_api(Template, api_options) do
21
+ get_request(:path => '/haml_str') do |c|
22
+ c.response.should =~ %r{<h1>Header</h1>}
23
+ end
24
+ end
25
+ end
26
+
22
27
  it 'renders a markdown template with default haml layout' do
23
28
  with_api(Template, api_options) do
24
29
  get_request(:path => '/joke') do |c|
25
- c.response.should =~ %r{<code>"Arr, I dunno matey -- but it's drivin' me nuts!"\s*</code>}m
30
+ c.response.should =~ %r{<code>Arr, I dunno matey -- but it is driving me nuts!\s*</code>}m
26
31
  end
27
32
  end
28
33
  end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ class DummyServer < Goliath::API
4
+
5
+ end
6
+
7
+ describe "with_api" do
8
+ let(:err) { Proc.new { fail "API request failed" } }
9
+
10
+ it "should log in file if requested" do
11
+ with_api(DummyServer, :log_file => "test.log") do |api|
12
+ get_request({},err)
13
+ end
14
+ File.exist?("test.log").should be_true
15
+ File.unlink("test.log")
16
+ end
17
+
18
+ it "should log on console if requested" do
19
+ with_api(DummyServer, {:log_stdout => true }) do |api|
20
+ api.logger.outputters.select {|o| o.is_a? Log4r::StdoutOutputter}.should_not be_empty
21
+ EM.stop
22
+ end
23
+ end
24
+
25
+ it "should be verbose if asked" do
26
+ with_api(DummyServer, {:verbose => true, :log_stdout => true }) do |api|
27
+ api.logger.level.should == Log4r::DEBUG
28
+ EM.stop
29
+ end
30
+
31
+ end
32
+
33
+ end
@@ -1,12 +1,42 @@
1
1
  require 'spec_helper'
2
2
  require 'json'
3
- require File.join(File.dirname(__FILE__), '../../', 'examples/valid')
4
3
 
5
- describe Valid do
4
+ class ValidSingleParam < Goliath::API
5
+ use Goliath::Rack::Params
6
+ use Goliath::Rack::Validation::RequiredParam, {:key => 'test'}
7
+
8
+ # If you are using Golaith version <=0.9.1 you need to use Goliath::Rack::ValidationError
9
+ # to prevent the request from remaining open after an error occurs
10
+ #use Goliath::Rack::ValidationError
11
+
12
+ def response(env)
13
+ [200, {}, 'OK']
14
+ end
15
+ end
16
+
17
+
18
+ class ValidNestedParams < Goliath::API
19
+ use Goliath::Rack::Params
20
+
21
+ # For this validation to pass you need to have this as parameter (json body here)
22
+ # {
23
+ # 'data' : {
24
+ # 'login' : 'my_login'
25
+ # }
26
+ # }
27
+ #
28
+ use Goliath::Rack::Validation::RequiredParam, :key => %w(data login)
29
+
30
+ def response(env)
31
+ [200, {}, 'OK']
32
+ end
33
+ end
34
+
35
+ describe ValidSingleParam do
6
36
  let(:err) { Proc.new { fail "API request failed" } }
7
37
 
8
38
  it 'returns OK with param' do
9
- with_api(Valid) do
39
+ with_api(ValidSingleParam) do
10
40
  get_request({:query => {:test => 'test'}}, err) do |c|
11
41
  c.response.should == 'OK'
12
42
  end
@@ -14,9 +44,9 @@ describe Valid do
14
44
  end
15
45
 
16
46
  it 'returns error without param' do
17
- with_api(Valid) do
47
+ with_api(ValidSingleParam) do
18
48
  get_request({}, err) do |c|
19
- c.response.should == '[:error, "Test identifier missing"]'
49
+ c.response.should == '[:error, "test identifier missing"]'
20
50
  end
21
51
  end
22
52
  end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+ require File.join(File.dirname(__FILE__), '../../', 'lib/goliath/test_helper_ws')
3
+ require File.join(File.dirname(__FILE__), '../../', 'lib/goliath')
4
+ require File.join(File.dirname(__FILE__), '../../', 'lib/goliath/websocket')
5
+
6
+ class WebSocketEndPoint < Goliath::WebSocket
7
+ def on_open(env)
8
+ end
9
+
10
+ def on_error(env, error)
11
+ env.logger.error error
12
+ end
13
+
14
+ def on_message(env, msg)
15
+ env.stream_send(msg)
16
+ end
17
+
18
+ def on_close(env)
19
+ end
20
+ end
21
+
22
+ describe "WebSocket" do
23
+ include Goliath::TestHelper
24
+
25
+ let(:err) { Proc.new { |c| fail "HTTP Request failed #{c.response}" } }
26
+
27
+ it "should accept connection" do
28
+ with_api(WebSocketEndPoint, {:verbose => true, :log_stdout => true}) do |server|
29
+ WebSocketEndPoint.any_instance.should_receive(:on_open)
30
+ ws_client_connect('/ws')
31
+ end
32
+ end
33
+
34
+ it "should accept traffic" do
35
+ with_api(WebSocketEndPoint, {:verbose => true, :log_stdout => true}) do |server|
36
+ ws_client_connect('/ws') do |client|
37
+ client.send "hello"
38
+ client.receive.should == "hello"
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+
@@ -5,26 +5,9 @@ describe Goliath::API do
5
5
 
6
6
  DummyApi = Class.new(Goliath::API)
7
7
 
8
- describe 'middlewares' do
8
+ describe "middlewares" do
9
9
  it "doesn't change after multi calls" do
10
- 2.times { Goliath::API.should have(2).middlewares }
10
+ 2.times { DummyApi.should have(2).middlewares }
11
11
  end
12
12
  end
13
-
14
- describe ".maps?" do
15
- context "when not using maps" do
16
- it "returns false" do
17
- DummyApi.maps?.should be_false
18
- end
19
- end
20
-
21
- context "when using maps" do
22
- it "returns true" do
23
- DummyApi.map "/foo"
24
- DummyApi.maps?.should be_true
25
- end
26
- end
27
- end
28
-
29
-
30
13
  end
@@ -43,7 +43,10 @@ describe Goliath::Connection do
43
43
  request_mock = mock("parser").as_null_object
44
44
  request_mock.should_receive(:<<)
45
45
 
46
+ current_mock = mock("current").as_null_object
47
+
46
48
  @c.instance_variable_set("@parser", request_mock)
49
+ @c.instance_variable_set("@current", current_mock)
47
50
  @c.receive_data('more_data')
48
51
  end
49
52
 
@@ -30,13 +30,13 @@ describe Goliath::Rack::Formatters::JSON do
30
30
  @app.should_receive(:call).and_return([200, {'Content-Type' => 'application/json'}, {:a => 1, :b => 2}])
31
31
 
32
32
  status, header, body = @js.call({})
33
- lambda { Yajl::Parser.parse(body.first)['a'].should == 1 }.should_not raise_error
33
+ lambda { MultiJson.load(body.first)['a'].should == 1 }.should_not raise_error
34
34
  end
35
35
 
36
36
  it "doesn't format to json if the type is not application/json" do
37
37
  @app.should_receive(:call).and_return([200, {'Content-Type' => 'application/xml'}, {:a => 1, :b => 2}])
38
38
 
39
- Yajl::Parser.should_not_receive(:encode)
39
+ MultiJson.should_not_receive(:dump)
40
40
  status, header, body = @js.call({})
41
41
  body[:a].should == 1
42
42
  end
@@ -44,7 +44,7 @@ describe Goliath::Rack::Formatters::JSON do
44
44
  it 'returns the status and headers' do
45
45
  @app.should_receive(:call).and_return([200, {'Content-Type' => 'application/xml'}, {:a => 1, :b => 2}])
46
46
 
47
- Yajl::Parser.should_not_receive(:encode)
47
+ MultiJson.should_not_receive(:dump)
48
48
  status, header, body = @js.call({})
49
49
  status.should == 200
50
50
  header.should == {'Content-Type' => 'application/xml'}
@@ -52,6 +52,19 @@ describe Goliath::Rack::Heartbeat do
52
52
  headers.should == {}
53
53
  body.should == nil
54
54
  end
55
+
56
+ it 'does not log the request by default' do
57
+ @env['PATH_INFO'] = '/status'
58
+ @hb.call(@env)
59
+ @env[Goliath::Constants::RACK_LOGGER].should == Log4r::Logger.root
60
+ end
61
+
62
+ it 'logs the request only if asked' do
63
+ @env['PATH_INFO'] = '/status'
64
+ @hb = Goliath::Rack::Heartbeat.new(@app, :log => true)
65
+ @hb.call(@env)
66
+ @env[Goliath::Constants::RACK_LOGGER].should_not == Log4r::Logger.root
67
+ end
55
68
  end
56
69
  end
57
70
 
@@ -19,7 +19,6 @@ describe Goliath::Rack::Params do
19
19
 
20
20
  ret = @params.retrieve_params(@env)
21
21
  ret['foo'].should == 'bar'
22
- ret[:foo].should == 'bar'
23
22
  ret['baz'].should == 'bonkey'
24
23
  end
25
24
 
@@ -39,8 +38,6 @@ describe Goliath::Rack::Params do
39
38
  ret['foo'].should == 'bar'
40
39
  ret['baz'].should == 'bonkey'
41
40
  ret['zonk'].should == {'donk' => 'monk'}
42
- ret[:zonk].should == {'donk' => 'monk'}
43
- ret[:zonk][:donk].should == 'monk'
44
41
  end
45
42
 
46
43
  it 'parses arrays of data' do
@@ -50,7 +47,6 @@ describe Goliath::Rack::Params do
50
47
  ret['foo'].is_a?(Array).should be_true
51
48
  ret['foo'].length.should == 3
52
49
  ret['foo'].should == %w(bar baz foos)
53
- ret[:foo].should == %w(bar baz foos)
54
50
  end
55
51
 
56
52
  it 'parses multipart data' do
@@ -71,7 +67,6 @@ Berry\r
71
67
 
72
68
  ret = @params.retrieve_params(@env)
73
69
  ret['submit-name'].should == 'Larry'
74
- ret[:"submit-name"].should == 'Larry'
75
70
  ret['submit-name-with-content'].should == 'Berry'
76
71
  end
77
72
 
@@ -145,13 +140,12 @@ Berry\r
145
140
 
146
141
  ret = @params.retrieve_params(@env)
147
142
  ret['foo'].should == 'bar'
148
- ret[:foo].should == 'bar'
149
143
  end
150
-
144
+
151
145
  it "handles empty input gracefully on JSON" do
152
146
  @env['CONTENT_TYPE'] = 'application/json'
153
147
  @env['rack.input'] = StringIO.new
154
-
148
+
155
149
  ret = @params.retrieve_params(@env)
156
150
  ret.should be_empty
157
151
  end