goliath 1.0.3 → 1.0.4
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.
- checksums.yaml +7 -0
- data/examples/api_proxy.rb +2 -0
- data/examples/around.rb +38 -0
- data/examples/clone.rb +26 -0
- data/examples/router.rb +15 -0
- data/examples/test.rb +31 -0
- data/examples/upload.rb +17 -0
- data/goliath.gemspec +4 -3
- data/lib/goliath/api.rb +5 -2
- data/lib/goliath/connection.rb +1 -1
- data/lib/goliath/rack/params.rb +13 -14
- data/lib/goliath/rack/validation/param.rb +3 -3
- data/lib/goliath/request.rb +11 -11
- data/lib/goliath/server.rb +0 -1
- data/lib/goliath/version.rb +1 -1
- data/spec/integration/http_log_spec.rb +1 -1
- data/spec/integration/websocket_spec.rb +1 -1
- data/spec/unit/connection_spec.rb +7 -7
- data/spec/unit/rack/default_mime_type_spec.rb +3 -3
- data/spec/unit/rack/formatters/json_spec.rb +2 -2
- data/spec/unit/rack/formatters/plist_spec.rb +1 -1
- data/spec/unit/rack/formatters/xml_spec.rb +2 -2
- data/spec/unit/rack/formatters/yaml_spec.rb +2 -2
- data/spec/unit/rack/heartbeat_spec.rb +2 -2
- data/spec/unit/rack/params_spec.rb +8 -1
- data/spec/unit/rack/render_spec.rb +1 -1
- data/spec/unit/rack/validation/boolean_value_spec.rb +2 -2
- data/spec/unit/rack/validation/default_params_spec.rb +1 -1
- data/spec/unit/rack/validation/numeric_range_spec.rb +1 -1
- data/spec/unit/rack/validation/param_spec.rb +4 -4
- data/spec/unit/rack/validation/request_method_spec.rb +4 -4
- data/spec/unit/rack/validation/required_param_spec.rb +3 -3
- data/spec/unit/rack/validation/required_value_spec.rb +1 -1
- data/spec/unit/request_spec.rb +15 -6
- data/spec/unit/runner_spec.rb +14 -14
- data/spec/unit/server_spec.rb +11 -23
- metadata +82 -123
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c49ef49ca7b81daf949084e54013fe33751d9461
|
4
|
+
data.tar.gz: c9bd1ae49086f0fa8ff01dd8617994156ff1b448
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4d9e9698db573be7495f89394bae42ad613397489a5e979994b29ee1518238c73884444f8be2bdef7b7bea936a1bced59b07e7d85eb5cec5dc1e2fb75758de8a
|
7
|
+
data.tar.gz: 4a800250911ccb181214f88c43442539b18cb96676b960ffa8e7a3acddc1aa3413d83c58bab1b389280d09f4822ac97f815be9db80cd8dde52483a006e991062
|
data/examples/api_proxy.rb
CHANGED
data/examples/around.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:<< '../lib' << 'lib'
|
3
|
+
|
4
|
+
require 'goliath'
|
5
|
+
|
6
|
+
class ApiValidationAroundware
|
7
|
+
include Goliath::Rack::SimpleAroundware
|
8
|
+
class InvalidApiKeyError < Goliath::Validation::BadRequestError; end
|
9
|
+
|
10
|
+
def pre_process
|
11
|
+
validate_api_key!
|
12
|
+
env.logger.info "past api_key validation" #<-- this is output, then an empty response header & body as if it is just hanging...
|
13
|
+
Goliath::Connection::AsyncResponse
|
14
|
+
end
|
15
|
+
|
16
|
+
def post_process
|
17
|
+
[status, headers, body]
|
18
|
+
end
|
19
|
+
|
20
|
+
def validate_api_key!
|
21
|
+
server_api_key = env['config']['server_api_key'].to_s
|
22
|
+
if api_key != server_api_key
|
23
|
+
raise InvalidApiKeyError
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# retreive the client's api_key
|
28
|
+
def api_key
|
29
|
+
env['HTTP_API_KEY'].to_s
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
class AwesomeApiWithLogging < Goliath::API
|
34
|
+
use Goliath::Rack::SimpleAroundwareFactory, ApiValidationAroundware
|
35
|
+
def response(env)
|
36
|
+
[200, {}, "Hello"]
|
37
|
+
end
|
38
|
+
end
|
data/examples/clone.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:<< '../lib' << 'lib'
|
3
|
+
|
4
|
+
require 'goliath'
|
5
|
+
|
6
|
+
class RandomAPI2 < Goliath::API
|
7
|
+
use Goliath::Rack::Params
|
8
|
+
use Goliath::Rack::Validation::Param, :key => 'user'
|
9
|
+
|
10
|
+
def response(env)
|
11
|
+
[200, {}, "Hello 2!"]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
class Router < Goliath::API
|
16
|
+
map '/', RandomAPI2
|
17
|
+
end
|
18
|
+
|
19
|
+
# class PlainApi < Goliath::API
|
20
|
+
# use Goliath::Rack::Params
|
21
|
+
# use Goliath::Rack::Validation::Param, :key => 'user'
|
22
|
+
|
23
|
+
# def response(env)
|
24
|
+
# [200, {}, "Hello 2!"]
|
25
|
+
# end
|
26
|
+
# end
|
data/examples/router.rb
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:<< '../lib' << 'lib'
|
3
|
+
|
4
|
+
require 'goliath'
|
5
|
+
require 'test'
|
6
|
+
|
7
|
+
|
8
|
+
class Router < Goliath::API
|
9
|
+
get '/v1/app/:appid/binary/:key', RawFileApp
|
10
|
+
put '/v1/app/:appid/binary/:key', RawFileApp
|
11
|
+
|
12
|
+
not_found do
|
13
|
+
run Proc.new { |env| [404, {"Content-Type" => "text/html"}, "not found"] }
|
14
|
+
end
|
15
|
+
end
|
data/examples/test.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:<< '../lib' << 'lib'
|
3
|
+
|
4
|
+
require 'goliath'
|
5
|
+
|
6
|
+
class RawFileApp < Goliath::API
|
7
|
+
use Goliath::Rack::Params # parse & merge query and body parameters
|
8
|
+
use Goliath::Rack::DefaultMimeType # cleanup accepted media types
|
9
|
+
use Goliath::Rack::Formatters::JSON # JSON output formatter
|
10
|
+
use Goliath::Rack::Render # auto-negotiate response format
|
11
|
+
|
12
|
+
def response(env)
|
13
|
+
p params
|
14
|
+
p params['key2']
|
15
|
+
p params[:key2]
|
16
|
+
obj = {
|
17
|
+
somekey: 'val',
|
18
|
+
otherkey: 42
|
19
|
+
}
|
20
|
+
[200, { 'Content-Type' => 'application/json' }, obj]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Router < Goliath::API
|
25
|
+
get '/v1/app/:appid/binary/:key', RawFileApp
|
26
|
+
put '/v1/app/:appid/binary/:key', RawFileApp
|
27
|
+
|
28
|
+
not_found do
|
29
|
+
run Proc.new { |env| [404, {"Content-Type" => "text/html"}, "not found"] }
|
30
|
+
end
|
31
|
+
end
|
data/examples/upload.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
$:<< '../lib' << 'lib'
|
3
|
+
|
4
|
+
require 'goliath'
|
5
|
+
|
6
|
+
class Upload < Goliath::API
|
7
|
+
|
8
|
+
def on_headers(env, h)
|
9
|
+
if h['Expect'] == '100-continue'
|
10
|
+
env.stream_send "HTTP/1.1 100 Continue\r\n"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def response(env)
|
15
|
+
[200, {}, "oh hai"]
|
16
|
+
end
|
17
|
+
end
|
data/goliath.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.add_dependency 'eventmachine', '>= 1.0.0.beta.4'
|
18
18
|
s.add_dependency 'em-synchrony', '>= 1.0.0'
|
19
19
|
s.add_dependency 'em-websocket', "0.3.8"
|
20
|
-
s.add_dependency 'http_parser.rb', '0.6.0
|
20
|
+
s.add_dependency 'http_parser.rb', '0.6.0'
|
21
21
|
s.add_dependency 'log4r'
|
22
22
|
|
23
23
|
s.add_dependency 'rack', '>=1.2.2'
|
@@ -40,8 +40,9 @@ Gem::Specification.new do |s|
|
|
40
40
|
s.add_development_dependency 'haml', '>=3.0.25'
|
41
41
|
s.add_development_dependency 'yard'
|
42
42
|
|
43
|
-
s.add_development_dependency 'guard'
|
44
|
-
s.add_development_dependency 'guard-rspec'
|
43
|
+
s.add_development_dependency 'guard', '~> 1.8.3'
|
44
|
+
s.add_development_dependency 'guard-rspec', '~> 3.1.0'
|
45
|
+
s.add_development_dependency 'listen', '~> 1.3.1'
|
45
46
|
|
46
47
|
if RUBY_PLATFORM != 'java'
|
47
48
|
s.add_development_dependency 'yajl-ruby'
|
data/lib/goliath/api.rb
CHANGED
@@ -175,8 +175,11 @@ module Goliath
|
|
175
175
|
env[ASYNC_CALLBACK].call(validation_error(e.status_code, e.message))
|
176
176
|
|
177
177
|
rescue Exception => e
|
178
|
-
|
179
|
-
|
178
|
+
logthis = "#{e.backtrace[0]}: #{e.message} (#{e.class})\n"
|
179
|
+
e.backtrace[1..-1].each do |bt|
|
180
|
+
logthis += " from #{bt}\n"
|
181
|
+
end
|
182
|
+
env.logger.error(logthis)
|
180
183
|
env[RACK_EXCEPTION] = e
|
181
184
|
|
182
185
|
message = Goliath.env?(:production) ? 'An error happened' : e.message
|
data/lib/goliath/connection.rb
CHANGED
@@ -22,7 +22,7 @@ module Goliath
|
|
22
22
|
|
23
23
|
@parser = Http::Parser.new
|
24
24
|
@parser.on_headers_complete = proc do |h|
|
25
|
-
env =
|
25
|
+
env = Goliath::Env.new
|
26
26
|
env[SERVER_PORT] = port.to_s
|
27
27
|
env[RACK_LOGGER] = logger
|
28
28
|
env[OPTIONS] = options
|
data/lib/goliath/rack/params.rb
CHANGED
@@ -17,16 +17,15 @@ module Goliath
|
|
17
17
|
module Parser
|
18
18
|
def retrieve_params(env)
|
19
19
|
params = env['params'] || {}
|
20
|
-
|
20
|
+
begin
|
21
|
+
params.merge!(::Rack::Utils.parse_nested_query(env['QUERY_STRING']))
|
22
|
+
if env['rack.input']
|
23
|
+
post_params = ::Rack::Utils::Multipart.parse_multipart(env)
|
24
|
+
unless post_params
|
25
|
+
body = env['rack.input'].read
|
26
|
+
env['rack.input'].rewind
|
21
27
|
|
22
|
-
|
23
|
-
post_params = ::Rack::Utils::Multipart.parse_multipart(env)
|
24
|
-
unless post_params
|
25
|
-
body = env['rack.input'].read
|
26
|
-
env['rack.input'].rewind
|
27
|
-
|
28
|
-
unless body.empty?
|
29
|
-
begin
|
28
|
+
unless body.empty?
|
30
29
|
post_params = case(env['CONTENT_TYPE'])
|
31
30
|
when URL_ENCODED then
|
32
31
|
::Rack::Utils.parse_nested_query(body)
|
@@ -40,14 +39,14 @@ module Goliath
|
|
40
39
|
else
|
41
40
|
{}
|
42
41
|
end
|
43
|
-
|
44
|
-
|
42
|
+
else
|
43
|
+
post_params = {}
|
45
44
|
end
|
46
|
-
else
|
47
|
-
post_params = {}
|
48
45
|
end
|
46
|
+
params.merge!(post_params)
|
49
47
|
end
|
50
|
-
|
48
|
+
rescue StandardError => e
|
49
|
+
raise Goliath::Validation::BadRequestError, "Invalid parameters: #{e.class.to_s}"
|
51
50
|
end
|
52
51
|
params
|
53
52
|
end
|
@@ -49,7 +49,7 @@ module Goliath
|
|
49
49
|
include Goliath::Rack::Validator
|
50
50
|
include Coerce
|
51
51
|
include Required
|
52
|
-
|
52
|
+
UNKNOWN_OPTIONS = "Unknown options: %s"
|
53
53
|
|
54
54
|
attr_reader :key, :type, :optional, :message, :default
|
55
55
|
|
@@ -71,7 +71,7 @@ module Goliath
|
|
71
71
|
@optional = opts.delete(:optional) || false
|
72
72
|
@key = opts.delete(:key)
|
73
73
|
raise Exception.new("key option required") unless @key
|
74
|
-
|
74
|
+
|
75
75
|
@type = opts.delete(:type) || @key
|
76
76
|
@message = opts.delete(:message) || 'identifier missing'
|
77
77
|
@default = opts.delete(:default)
|
@@ -79,7 +79,7 @@ module Goliath
|
|
79
79
|
coerce_setup!(opts)
|
80
80
|
required_setup!(opts)
|
81
81
|
|
82
|
-
raise Exception.new(
|
82
|
+
raise Exception.new(UNKNOWN_OPTIONS % opts.inspect) unless opts.empty?
|
83
83
|
end
|
84
84
|
|
85
85
|
def call(env)
|
data/lib/goliath/request.rb
CHANGED
@@ -87,20 +87,20 @@ module Goliath
|
|
87
87
|
@env[SERVER_PORT] = port if port
|
88
88
|
end
|
89
89
|
|
90
|
-
|
90
|
+
begin
|
91
|
+
uri = URI(parser.request_url)
|
91
92
|
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
93
|
+
@env[REQUEST_METHOD] = parser.http_method
|
94
|
+
@env[REQUEST_URI] = parser.request_url
|
95
|
+
@env[QUERY_STRING] = uri.query
|
96
|
+
@env[HTTP_VERSION] = parser.http_version.join('.')
|
97
|
+
@env[SCRIPT_NAME] = ""
|
98
|
+
@env[REQUEST_PATH] = uri.path
|
99
|
+
@env[PATH_INFO] = uri.path
|
100
|
+
@env[FRAGMENT] = uri.fragment
|
100
101
|
|
101
|
-
|
102
|
+
yield if block_given?
|
102
103
|
|
103
|
-
begin
|
104
104
|
@env[ASYNC_HEADERS].call(@env, h) if @env[ASYNC_HEADERS]
|
105
105
|
rescue Exception => e
|
106
106
|
server_exception(e)
|
data/lib/goliath/server.rb
CHANGED
data/lib/goliath/version.rb
CHANGED
@@ -35,7 +35,7 @@ describe "WebSocket" do
|
|
35
35
|
with_api(WebSocketEndPoint, {:verbose => true, :log_stdout => true}) do |server|
|
36
36
|
ws_client_connect('/ws') do |client|
|
37
37
|
client.send "hello"
|
38
|
-
client.receive.should == "hello"
|
38
|
+
client.receive.data.should == "hello"
|
39
39
|
end
|
40
40
|
end
|
41
41
|
end
|
@@ -7,25 +7,25 @@ describe Goliath::Connection do
|
|
7
7
|
|
8
8
|
describe 'configuration' do
|
9
9
|
it 'accepts an app' do
|
10
|
-
app =
|
10
|
+
app = double('app')
|
11
11
|
@c.app = app
|
12
12
|
@c.app.should == app
|
13
13
|
end
|
14
14
|
|
15
15
|
it 'accepts a logger' do
|
16
|
-
logger =
|
16
|
+
logger = double('logger')
|
17
17
|
@c.logger = logger
|
18
18
|
@c.logger.should == logger
|
19
19
|
end
|
20
20
|
|
21
21
|
it 'accepts a status object' do
|
22
|
-
status =
|
22
|
+
status = double('status')
|
23
23
|
@c.status = status
|
24
24
|
@c.status.should == status
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'accepts config' do
|
28
|
-
config =
|
28
|
+
config = double('config')
|
29
29
|
@c.config = config
|
30
30
|
@c.config.should == config
|
31
31
|
end
|
@@ -40,10 +40,10 @@ describe Goliath::Connection do
|
|
40
40
|
|
41
41
|
describe 'receive_data' do
|
42
42
|
it 'passes data to the http parser' do
|
43
|
-
request_mock =
|
43
|
+
request_mock = double("parser").as_null_object
|
44
44
|
request_mock.should_receive(:<<)
|
45
45
|
|
46
|
-
current_mock =
|
46
|
+
current_mock = double("current").as_null_object
|
47
47
|
|
48
48
|
@c.instance_variable_set("@parser", request_mock)
|
49
49
|
@c.instance_variable_set("@current", current_mock)
|
@@ -51,7 +51,7 @@ describe Goliath::Connection do
|
|
51
51
|
end
|
52
52
|
|
53
53
|
it "closes the connection when a parse error is received" do
|
54
|
-
current_mock =
|
54
|
+
current_mock = double("current").as_null_object
|
55
55
|
current_mock.should_receive(:close)
|
56
56
|
|
57
57
|
@c.instance_variable_set("@current", current_mock)
|
@@ -3,11 +3,11 @@ require 'goliath/env'
|
|
3
3
|
require 'goliath/rack/default_mime_type'
|
4
4
|
|
5
5
|
describe Goliath::Rack::DefaultMimeType do
|
6
|
-
let(:app) {
|
6
|
+
let(:app) { double('app').as_null_object }
|
7
7
|
let(:dmt) { Goliath::Rack::DefaultMimeType.new(app) }
|
8
8
|
let(:env) do
|
9
9
|
env = Goliath::Env.new
|
10
|
-
env['status'] =
|
10
|
+
env['status'] = double('status').as_null_object
|
11
11
|
env
|
12
12
|
end
|
13
13
|
|
@@ -31,4 +31,4 @@ describe Goliath::Rack::DefaultMimeType do
|
|
31
31
|
env['HTTP_ACCEPT'].should == '*/*'
|
32
32
|
end
|
33
33
|
end
|
34
|
-
end
|
34
|
+
end
|
@@ -8,7 +8,7 @@ describe Goliath::Rack::Formatters::JSON do
|
|
8
8
|
|
9
9
|
describe 'with a formatter' do
|
10
10
|
before(:each) do
|
11
|
-
@app =
|
11
|
+
@app = double('app').as_null_object
|
12
12
|
@js = Goliath::Rack::Formatters::JSON.new(@app)
|
13
13
|
end
|
14
14
|
|
@@ -21,7 +21,7 @@ describe Goliath::Rack::Formatters::JSON do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it 'calls the app with the provided environment' do
|
24
|
-
env_mock =
|
24
|
+
env_mock = double('env').as_null_object
|
25
25
|
@app.should_receive(:call).with(env_mock).and_return([200, {}, {"a" => 1}])
|
26
26
|
@js.call(env_mock)
|
27
27
|
end
|
@@ -9,7 +9,7 @@ describe Goliath::Rack::Formatters::XML do
|
|
9
9
|
|
10
10
|
describe 'with a formatter' do
|
11
11
|
before(:each) do
|
12
|
-
@app =
|
12
|
+
@app = double('app').as_null_object
|
13
13
|
@xml = Goliath::Rack::Formatters::XML.new(@app)
|
14
14
|
end
|
15
15
|
|
@@ -22,7 +22,7 @@ describe Goliath::Rack::Formatters::XML do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
it 'calls the app with the provided environment' do
|
25
|
-
env_mock =
|
25
|
+
env_mock = double('env').as_null_object
|
26
26
|
@app.should_receive(:call).with(env_mock).and_return([200, {}, {"a" => 1}])
|
27
27
|
@xml.call(env_mock)
|
28
28
|
end
|