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.
- data/.gitignore +3 -0
- data/Guardfile +8 -0
- data/HISTORY.md +10 -0
- data/LICENSE +1 -1
- data/README.md +28 -29
- data/Rakefile +10 -2
- data/examples/activerecord/config/srv.rb +2 -1
- data/examples/activerecord/srv.rb +14 -5
- data/examples/api_proxy.rb +3 -7
- data/examples/around.rb +38 -0
- data/examples/async_aroundware_demo.rb +2 -2
- data/examples/async_upload.rb +1 -1
- data/examples/auth_and_rate_limit.rb +1 -1
- data/examples/clone.rb +26 -0
- data/examples/config/websocket.rb +1 -0
- data/examples/custom_logs.rb +21 -0
- data/examples/custom_server.rb +6 -44
- data/examples/early_abort.rb +6 -3
- data/examples/echo.rb +1 -1
- data/examples/fiber_pool.rb +35 -0
- data/examples/grape/config/apiserver.rb +8 -0
- data/examples/grape/server.rb +67 -0
- data/examples/gziped.rb +1 -1
- data/examples/params.rb +36 -0
- data/examples/rasterize/rasterize.rb +1 -2
- data/examples/router.rb +15 -0
- data/examples/template.rb +14 -7
- data/examples/test.rb +31 -0
- data/examples/upload.rb +17 -0
- data/examples/views/joke.markdown +4 -4
- data/examples/websocket.rb +39 -0
- data/examples/ws/favicon.ico +0 -0
- data/examples/ws/index.erb +50 -0
- data/goliath.gemspec +24 -6
- data/lib/goliath/api.rb +15 -82
- data/lib/goliath/application.rb +3 -17
- data/lib/goliath/connection.rb +16 -9
- data/lib/goliath/constants.rb +2 -0
- data/lib/goliath/env.rb +2 -3
- data/lib/goliath/goliath.rb +24 -34
- data/lib/goliath/plugins/latency.rb +7 -3
- data/lib/goliath/rack/builder.rb +1 -37
- data/lib/goliath/rack/favicon.rb +31 -0
- data/lib/goliath/rack/formatters/json.rb +1 -1
- data/lib/goliath/rack/heartbeat.rb +1 -0
- data/lib/goliath/rack/jsonp.rb +1 -0
- data/lib/goliath/rack/params.rb +2 -17
- data/lib/goliath/rack/render.rb +0 -1
- data/lib/goliath/rack/templates.rb +18 -7
- data/lib/goliath/rack/types/base.rb +24 -0
- data/lib/goliath/rack/types/boolean.rb +18 -0
- data/lib/goliath/rack/types/core.rb +19 -0
- data/lib/goliath/rack/types/symbol.rb +16 -0
- data/lib/goliath/rack/types.rb +10 -0
- data/lib/goliath/rack/validation/coerce.rb +48 -0
- data/lib/goliath/rack/validation/param.rb +113 -0
- data/lib/goliath/rack/validation/request_method.rb +1 -1
- data/lib/goliath/rack/validation/required.rb +47 -0
- data/lib/goliath/rack/validation/required_param.rb +42 -17
- data/lib/goliath/rack/validation.rb +3 -0
- data/lib/goliath/rack.rb +2 -2
- data/lib/goliath/request.rb +41 -9
- data/lib/goliath/response.rb +0 -2
- data/lib/goliath/runner.rb +55 -4
- data/lib/goliath/server.rb +7 -3
- data/lib/goliath/test_helper.rb +70 -16
- data/lib/goliath/test_helper_ws.rb +42 -0
- data/lib/goliath/version.rb +1 -1
- data/lib/goliath/websocket.rb +80 -0
- data/pkg/goliath-0.9.4.gem +0 -0
- data/pkg/goliath-1.0.0.beta.1.gem +0 -0
- data/spec/integration/async_request_processing.rb +1 -1
- data/spec/integration/early_abort_spec.rb +3 -10
- data/spec/integration/echo_spec.rb +8 -8
- data/spec/integration/jsonp_spec.rb +31 -0
- data/spec/integration/keepalive_spec.rb +2 -2
- data/spec/integration/template_spec.rb +10 -5
- data/spec/integration/test_helper_spec.rb +33 -0
- data/spec/integration/valid_spec.rb +35 -5
- data/spec/integration/websocket_spec.rb +44 -0
- data/spec/unit/api_spec.rb +2 -19
- data/spec/unit/connection_spec.rb +3 -0
- data/spec/unit/rack/formatters/json_spec.rb +3 -3
- data/spec/unit/rack/heartbeat_spec.rb +13 -0
- data/spec/unit/rack/params_spec.rb +2 -8
- data/spec/unit/rack/validation/param_spec.rb +443 -0
- data/spec/unit/rack/validation/request_method_spec.rb +5 -0
- data/spec/unit/rack/validation/required_param_spec.rb +71 -1
- data/spec/unit/runner_spec.rb +21 -7
- data/test/echo_test.rb +25 -0
- data/test/test_helper.rb +5 -0
- metadata +316 -78
- data/examples/env_use_statements.rb +0 -20
- data/examples/favicon.rb +0 -40
- data/examples/rack_routes.rb +0 -125
- data/examples/rasterize/thumb/f7ad4cb03e5bfd0e2c43db8e598fb3cd.png +0 -0
- data/examples/valid.rb +0 -17
- data/lib/goliath/deprecated/async_aroundware.rb +0 -133
- data/lib/goliath/deprecated/mongo_receiver.rb +0 -84
- data/lib/goliath/deprecated/response_receiver.rb +0 -97
- data/spec/integration/rack_routes_spec.rb +0 -169
- 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 =
|
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 =
|
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>
|
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
|
-
|
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(
|
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(
|
47
|
+
with_api(ValidSingleParam) do
|
18
48
|
get_request({}, err) do |c|
|
19
|
-
c.response.should == '[:error, "
|
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
|
+
|
data/spec/unit/api_spec.rb
CHANGED
@@ -5,26 +5,9 @@ describe Goliath::API do
|
|
5
5
|
|
6
6
|
DummyApi = Class.new(Goliath::API)
|
7
7
|
|
8
|
-
describe
|
8
|
+
describe "middlewares" do
|
9
9
|
it "doesn't change after multi calls" do
|
10
|
-
2.times {
|
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 {
|
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
|
-
|
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
|
-
|
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
|