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.

Files changed (37) hide show
  1. checksums.yaml +7 -0
  2. data/examples/api_proxy.rb +2 -0
  3. data/examples/around.rb +38 -0
  4. data/examples/clone.rb +26 -0
  5. data/examples/router.rb +15 -0
  6. data/examples/test.rb +31 -0
  7. data/examples/upload.rb +17 -0
  8. data/goliath.gemspec +4 -3
  9. data/lib/goliath/api.rb +5 -2
  10. data/lib/goliath/connection.rb +1 -1
  11. data/lib/goliath/rack/params.rb +13 -14
  12. data/lib/goliath/rack/validation/param.rb +3 -3
  13. data/lib/goliath/request.rb +11 -11
  14. data/lib/goliath/server.rb +0 -1
  15. data/lib/goliath/version.rb +1 -1
  16. data/spec/integration/http_log_spec.rb +1 -1
  17. data/spec/integration/websocket_spec.rb +1 -1
  18. data/spec/unit/connection_spec.rb +7 -7
  19. data/spec/unit/rack/default_mime_type_spec.rb +3 -3
  20. data/spec/unit/rack/formatters/json_spec.rb +2 -2
  21. data/spec/unit/rack/formatters/plist_spec.rb +1 -1
  22. data/spec/unit/rack/formatters/xml_spec.rb +2 -2
  23. data/spec/unit/rack/formatters/yaml_spec.rb +2 -2
  24. data/spec/unit/rack/heartbeat_spec.rb +2 -2
  25. data/spec/unit/rack/params_spec.rb +8 -1
  26. data/spec/unit/rack/render_spec.rb +1 -1
  27. data/spec/unit/rack/validation/boolean_value_spec.rb +2 -2
  28. data/spec/unit/rack/validation/default_params_spec.rb +1 -1
  29. data/spec/unit/rack/validation/numeric_range_spec.rb +1 -1
  30. data/spec/unit/rack/validation/param_spec.rb +4 -4
  31. data/spec/unit/rack/validation/request_method_spec.rb +4 -4
  32. data/spec/unit/rack/validation/required_param_spec.rb +3 -3
  33. data/spec/unit/rack/validation/required_value_spec.rb +1 -1
  34. data/spec/unit/request_spec.rb +15 -6
  35. data/spec/unit/runner_spec.rb +14 -14
  36. data/spec/unit/server_spec.rb +11 -23
  37. metadata +82 -123
@@ -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
@@ -2,6 +2,8 @@
2
2
 
3
3
  # Rewrites and proxies requests to a third-party API, with HTTP basic authentication.
4
4
 
5
+ $:<< '../lib' << 'lib'
6
+
5
7
  require 'goliath'
6
8
  require 'em-synchrony/em-http'
7
9
 
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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.beta.2'
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'
@@ -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
- env.logger.error(e.message)
179
- env.logger.error(e.backtrace.join("\n"))
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
@@ -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 = Thread.current[GOLIATH_ENV] = Goliath::Env.new
25
+ env = Goliath::Env.new
26
26
  env[SERVER_PORT] = port.to_s
27
27
  env[RACK_LOGGER] = logger
28
28
  env[OPTIONS] = options
@@ -17,16 +17,15 @@ module Goliath
17
17
  module Parser
18
18
  def retrieve_params(env)
19
19
  params = env['params'] || {}
20
- params.merge!(::Rack::Utils.parse_nested_query(env['QUERY_STRING']))
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
- 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
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
- rescue StandardError => e
44
- raise Goliath::Validation::BadRequestError, "Invalid parameters: #{e.class.to_s}"
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
- params.merge!(post_params)
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
- UKNOWN_OPTIONS = "Uknown options: %s"
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(UKNOWN_OPTIONS % opts.inspect) unless opts.empty?
82
+ raise Exception.new(UNKNOWN_OPTIONS % opts.inspect) unless opts.empty?
83
83
  end
84
84
 
85
85
  def call(env)
@@ -87,20 +87,20 @@ module Goliath
87
87
  @env[SERVER_PORT] = port if port
88
88
  end
89
89
 
90
- uri = URI(parser.request_url)
90
+ begin
91
+ uri = URI(parser.request_url)
91
92
 
92
- @env[REQUEST_METHOD] = parser.http_method
93
- @env[REQUEST_URI] = parser.request_url
94
- @env[QUERY_STRING] = uri.query
95
- @env[HTTP_VERSION] = parser.http_version.join('.')
96
- @env[SCRIPT_NAME] = uri.path
97
- @env[REQUEST_PATH] = uri.path
98
- @env[PATH_INFO] = uri.path
99
- @env[FRAGMENT] = uri.fragment
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
- yield if block_given?
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)
@@ -107,7 +107,6 @@ module Goliath
107
107
 
108
108
  # Stops the server running.
109
109
  def stop
110
- logger.info('Stopping server...')
111
110
  EM.stop
112
111
  end
113
112
 
@@ -1,4 +1,4 @@
1
1
  module Goliath
2
2
  # The current version of Goliath
3
- VERSION = '1.0.3'
3
+ VERSION = '1.0.4'
4
4
  end
@@ -33,7 +33,7 @@ describe HttpLog do
33
33
  let(:api_options) { { :config => config_file } }
34
34
 
35
35
  def mock_mongo(api)
36
- api.config['mongo'] = mock('mongo').as_null_object
36
+ api.config['mongo'] = double('mongo').as_null_object
37
37
  end
38
38
 
39
39
  it 'responds to requests' do
@@ -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 = mock('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 = mock('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 = mock('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 = mock('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 = mock("parser").as_null_object
43
+ request_mock = double("parser").as_null_object
44
44
  request_mock.should_receive(:<<)
45
45
 
46
- current_mock = mock("current").as_null_object
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 = mock("current").as_null_object
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) { mock('app').as_null_object }
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'] = mock('status').as_null_object
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 = mock('app').as_null_object
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 = mock('env').as_null_object
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
@@ -22,7 +22,7 @@ describe Goliath::Rack::Formatters::PLIST do
22
22
 
23
23
  describe 'with a formatter' do
24
24
  before(:each) do
25
- @app = mock('app').as_null_object
25
+ @app = double('app').as_null_object
26
26
  @m = Goliath::Rack::Formatters::PLIST.new(@app)
27
27
  end
28
28
 
@@ -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 = mock('app').as_null_object
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 = mock('env').as_null_object
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