agile-proxy 0.1.20 → 0.1.21

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7faec1aa540783f6fe42b674e1aeea119a470b15
4
- data.tar.gz: 1b01c98d23e6c95eb894601b4b05c3420a4219df
3
+ metadata.gz: dca50b88e4dff710583bb65d8dfeea362efe0194
4
+ data.tar.gz: ce452e942ba2a2b186b74d95e34048abb001098c
5
5
  SHA512:
6
- metadata.gz: 43f930138c348608ef2972536c2192c08716b4603a2bb9234108926da5d2d8e532a9618082a7a54b7f1212e5711d35eb79e0fcd455a31aa33dac3895ced35789
7
- data.tar.gz: bfbdf55b64323489c085822e565f1a32f2f3447684142f36c9bf48de9e2a7a9ffc7379bf7b400450e5dafbfe4ce1b799225c4c0bb4754d92950ee3ceb56a574e
6
+ metadata.gz: 42012c6b32b17916cdd7b5b592f434e7db5eb50dd6fd2b9c8f2cf6715631d295f490e4dc73fb72e6b6ba59c238572833c9d9da8167dbe0451ddecbef2ae4d04e
7
+ data.tar.gz: 3ed48c70d0599bb27c7956ccec8e7fa2c14e89feb9644f2375cf5703c793544c30c1a62252055b66fddf94888ef1827f5ea4500dad8148791f527ca9136000e2
data/.gitignore CHANGED
@@ -6,4 +6,5 @@ assets/ui/bower_components
6
6
  .yardoc
7
7
  db/*.db
8
8
  coverage/
9
- Gemfile.lock
9
+ Gemfile.lock
10
+ vendor/gems
data/README.md CHANGED
@@ -122,4 +122,5 @@ v0.1.18 - Fixed issue with integration test which was showing up now that travis
122
122
  v0.1.19 - Recordings now record the request spec id.
123
123
  Recordings can now be accessed via /request_specs/:request_spec_id/recordings to provide recordings specific to the request spec
124
124
  v0.1.20 - An individual request spec can now be set to 'record_requests' rather than requiring the whole application to be in record mode which slows down every request
125
+ v0.1.21 - Switched to goliath instead of thin. The gem now installs under jruby as well as other platforms.
125
126
 
@@ -21,11 +21,9 @@ Gem::Specification.new do |gem|
21
21
  gem.add_development_dependency 'faraday', '~> 0.9', '>= 0.9.0'
22
22
  gem.add_development_dependency 'poltergeist', '~> 1.5', '>= 1.5.1'
23
23
  gem.add_development_dependency 'selenium-webdriver', '~> 2.43', '>= 2.43.0'
24
- gem.add_development_dependency 'rack', '~> 1.6', '>= 1.6.0'
25
24
  gem.add_development_dependency 'guard', '~> 2.6', '>= 2.6.1'
26
25
  gem.add_development_dependency 'rb-inotify', '~> 0.9', '>= 0.9.5'
27
26
  gem.add_development_dependency 'cucumber', '~> 1.3', '>= 1.3.17'
28
- gem.add_development_dependency 'airborne', '~> 0.1', '>= 0.1.10'
29
27
  gem.add_development_dependency 'rest-client', '~> 1.7', '>= 1.7.2'
30
28
  gem.add_development_dependency 'require_all', '~> 1.3', '>= 1.3.2'
31
29
  gem.add_development_dependency 'faker', '~> 1.2', '>= 1.2.0'
@@ -35,16 +33,24 @@ Gem::Specification.new do |gem|
35
33
  gem.add_runtime_dependency 'eventmachine', '~> 1.0', '>= 1.0.3'
36
34
  gem.add_runtime_dependency 'em-synchrony', '~> 1.0', '>= 1.0.3'
37
35
  gem.add_runtime_dependency 'em-http-request', '~> 1.1', '>= 1.1.2'
38
- gem.add_runtime_dependency 'eventmachine_httpserver', '~> 0.2', '>= 0.2.1'
39
- gem.add_runtime_dependency 'http_parser.rb', '~> 0.6', '>= 0.6.0'
40
- gem.add_runtime_dependency 'multi_json', '~> 1.10', '>= 1.10.1'
41
- gem.add_runtime_dependency 'thin', '~> 1.6', '>= 1.6.2'
42
36
  gem.add_runtime_dependency 'grape', '~> 0.10', '>= 0.10.1'
43
37
  gem.add_runtime_dependency 'activerecord', '~> 4.2', '>= 4.2.0'
44
- gem.add_runtime_dependency 'sqlite3', '~> 1.3', '>= 1.3.10'
38
+ if RUBY_PLATFORM =~ /java/
39
+ #JVM Only
40
+ gem.add_runtime_dependency 'activerecord-jdbc-adapter'
41
+ gem.add_runtime_dependency 'activerecord-jdbcsqlite3-adapter'
42
+ else
43
+ #Non JVM
44
+ gem.add_runtime_dependency 'sqlite3', '~> 1.3', '>= 1.3.10'
45
+ end
46
+
47
+
48
+
45
49
  gem.add_runtime_dependency 'grape-kaminari', '~> 0.1', '>= 0.1.7'
46
50
  gem.add_runtime_dependency 'shoulda-matchers', '2.8.0.rc2'
47
51
  gem.add_runtime_dependency 'flavour_saver', '~> 0.3', '>= 0.3.4'
48
52
  gem.add_runtime_dependency 'thor', '~> 0.19', '>= 0.19.1'
49
- gem.add_runtime_dependency 'rack-parser', '~> 0.6', '>= 0.6.1'
53
+ gem.add_runtime_dependency 'goliath', '~> 1.0', '>= 1.0.4'
54
+ gem.add_runtime_dependency 'goliath-proxy', '~> 0.0', '>= 0.0.1'
55
+
50
56
  end
@@ -0,0 +1,19 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'goliath'
4
+ require 'active_support/core_ext/class/attribute_accessors'
5
+ class Echo < Goliath::API
6
+ cattr_accessor :counter
7
+ def response_code
8
+ ENV['STATUS_CODE'] || 200
9
+ end
10
+ def response(env)
11
+ self.counter = counter || 0
12
+ req_body = env['rack.input'].read
13
+ request_info = "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}"
14
+ res_body = request_info
15
+ res_body += "\n#{req_body}" unless req_body.empty?
16
+ self.counter += 1
17
+ [response_code, { 'HTTP-X-EchoServer' => request_info, 'HTTP-X-EchoCount' => "#{counter}" }, res_body]
18
+ end
19
+ end
@@ -36,8 +36,9 @@ module AgileProxy
36
36
  ]
37
37
  end
38
38
  request_spec = env['agile_proxy.request_spec']
39
+ exclude_headers = ['@env', 'rack.errors', 'rack.logger']
39
40
  if application.record_requests || (request_spec && request_spec.record_requests)
40
- application.recordings.create request_headers: request.headers,
41
+ application.recordings.create request_headers: request.headers.reject {|key, value| exclude_headers.include?(key)},
41
42
  request_body: body,
42
43
  request_url: request.url,
43
44
  request_method: request.request_method,
@@ -2,7 +2,6 @@ require 'agile_proxy/handlers/handler'
2
2
  require 'agile_proxy/model/request_spec'
3
3
  require 'agile_proxy/router'
4
4
  require 'agile_proxy/model/application'
5
- require 'rack/parser'
6
5
  require 'action_dispatch'
7
6
  require 'base64'
8
7
  module AgileProxy
@@ -1,4 +1,5 @@
1
1
  require_relative 'application'
2
+ require 'active_record'
2
3
  module AgileProxy
3
4
  #
4
5
  # = The recording model
@@ -1,24 +1,27 @@
1
1
  require 'uri'
2
2
  require 'eventmachine'
3
- require 'http/parser'
4
- require 'em-http'
5
- require 'evma_httpserver'
6
- require 'em-synchrony'
7
3
  require 'stringio'
8
4
  require 'rack'
5
+ require 'goliath/request'
6
+ require 'goliath/env'
9
7
 
10
8
  module AgileProxy
11
9
  #
12
10
  # = The Proxy Connection
13
11
  #
14
12
  # This class is the event machine connection used by the proxy. Every request creates a new instance of this
15
- class ProxyConnection < EventMachine::Connection
16
- attr_accessor :handler
13
+ class ProxyConnection < Goliath::Connection
14
+ def logger
15
+ ::AgileProxy.config.logger
16
+ end
17
17
  def post_init
18
- @parser = Http::Parser.new(self)
18
+ super
19
+ #@proxy_parser = Http::Parser.new(self)
20
+ @proxy_parser = Http::Parser.new
19
21
  end
20
22
 
21
23
  def receive_data(data)
24
+ #@proxy_parser << data
22
25
  @parser << data
23
26
  end
24
27
 
@@ -36,24 +39,25 @@ module AgileProxy
36
39
  end
37
40
 
38
41
  def on_message_complete
39
- if @parser.http_method == 'CONNECT'
40
- restart_with_ssl(@parser.request_url)
42
+ if @proxy_parser.http_method == 'CONNECT'
43
+ restart_with_ssl(@proxy_parser.request_url)
41
44
  else
42
45
  if @ssl
43
- uri = URI.parse(@parser.request_url)
46
+ uri = URI.parse(@proxy_parser.request_url)
44
47
  @url = "https://#{@ssl}#{[uri.path, uri.query].compact.join('?')}"
45
48
  else
46
- @url = @parser.request_url
49
+ @url = @proxy_parser.request_url
47
50
  end
48
51
  handle_request
49
52
  end
50
53
  end
51
54
 
55
+
52
56
  protected
53
57
 
54
58
  def restart_with_ssl(url)
55
59
  @ssl = url
56
- @parser = Http::Parser.new(self)
60
+ @proxy_parser = Http::Parser.new(self)
57
61
  @original_headers = @headers.clone
58
62
  send_data("HTTP/1.0 200 Connection established\r\nProxy-agent: Http-Flexible-Proxy/0.0.0\r\n\r\n")
59
63
  start_tls(
@@ -64,11 +68,9 @@ module AgileProxy
64
68
 
65
69
  def handle_request
66
70
  EM.synchrony do
67
- request = ActionDispatch::Request.new(env)
68
- request.params # This will populate action_dispatch.request.parameters
69
- handler.call(env).tap do |response|
70
- send_response(response)
71
- end
71
+ request = ::Goliath::Request.new(handler, self, env)
72
+ request.set_deferred_status :succeeded
73
+ request.process
72
74
  end
73
75
  end
74
76
 
@@ -79,10 +81,11 @@ module AgileProxy
79
81
  fake_input_buffer = StringIO.new(@body)
80
82
  fake_error_buffer = StringIO.new
81
83
  url_parsed = URI.parse(@url)
82
- @__env = {
84
+ @__env = ::Goliath::Env.new
85
+ @__env.merge!({
83
86
  'rack.input' => Rack::Lint::InputWrapper.new(fake_input_buffer),
84
87
  'rack.errors' => Rack::Lint::ErrorWrapper.new(fake_error_buffer),
85
- 'REQUEST_METHOD' => @parser.http_method,
88
+ 'REQUEST_METHOD' => @proxy_parser.http_method,
86
89
  'REQUEST_PATH' => url_parsed.path,
87
90
  'PATH_INFO' => url_parsed.path,
88
91
  'QUERY_STRING' => url_parsed.query || '',
@@ -90,9 +93,11 @@ module AgileProxy
90
93
  'rack.url_scheme' => url_parsed.scheme,
91
94
  'CONTENT_LENGTH' => @body.length,
92
95
  'SERVER_NAME' => url_parsed.host,
93
- 'SERVER_PORT' => url_parsed.port
96
+ 'SERVER_PORT' => url_parsed.port,
97
+ 'rack.logger' => logger
94
98
 
95
- }
99
+
100
+ })
96
101
  @headers.merge(@original_headers || {}).each do |name, value|
97
102
  converted_name = "HTTP_#{name.gsub(/-/, '_').upcase}"
98
103
  @__env[converted_name] = value
@@ -102,12 +107,6 @@ module AgileProxy
102
107
  @__env
103
108
  end
104
109
 
105
- def send_response(response)
106
- res = EM::DelegatedHttpResponse.new(self)
107
- res.status = response[0]
108
- res.headers = response[1]
109
- res.content = response[2]
110
- res.send_response
111
- end
110
+
112
111
  end
113
112
  end
@@ -3,13 +3,27 @@ require 'yaml'
3
3
  require 'cgi'
4
4
  require 'uri'
5
5
  require 'eventmachine'
6
- require 'thin'
7
6
  require 'grape'
8
7
  require 'agile_proxy/api/root'
9
8
  require 'agile_proxy/servers/api'
10
9
  require 'agile_proxy/servers/request_spec'
11
10
  require 'agile_proxy/servers/request_spec_direct'
12
11
  require 'forwardable'
12
+
13
+ require 'goliath/api'
14
+ require 'goliath/runner'
15
+
16
+ # Example demonstrating how to use a custom Goliath runner
17
+ #
18
+
19
+ class Custom < Goliath::API
20
+ def response(env)
21
+ [200, {}, "hello!"]
22
+ end
23
+ end
24
+
25
+
26
+
13
27
  module AgileProxy
14
28
  #
15
29
  # This class is responsible for controlling the underlying proxy and web servers
@@ -1,6 +1,7 @@
1
1
  require 'rack'
2
- require 'thin'
3
2
  require 'grape'
3
+ require 'goliath/api'
4
+ require 'goliath/runner'
4
5
  require 'agile_proxy/api/root'
5
6
 
6
7
  module AgileProxy
@@ -19,21 +20,19 @@ module AgileProxy
19
20
  # @param webserver_host [String] The host for the server to run on
20
21
  # @param webserver_port [Integer] The port for the server to run on
21
22
  def start(webserver_host, webserver_port)
22
- # The sinatra web server
23
- dispatch = Rack::Builder.app do
23
+ #
24
+ # The API runner
25
+ runner = ::Goliath::Runner.new([], nil)
26
+ runner.address = webserver_host
27
+ runner.port = webserver_port
28
+ runner.app = ::Goliath::Rack::Builder.app do
24
29
  use Rack::Static, root: File.join(ROOT, 'assets'), urls: ['/ui'], index: 'index.html'
25
30
  map '/api' do
26
31
  run ::AgileProxy::Api::Root.new
27
32
  end
28
33
  end
29
- # Start the web server.
30
- ::Rack::Server.start(
31
- app: dispatch,
32
- server: 'thin',
33
- Host: webserver_host,
34
- Port: webserver_port,
35
- signals: false
36
- )
34
+ runner.run
35
+
37
36
  end
38
37
  end
39
38
  end
@@ -1,4 +1,6 @@
1
1
  require 'eventmachine'
2
+ require 'goliath/api'
3
+ require 'goliath/proxy'
2
4
  module AgileProxy
3
5
  module Servers
4
6
  #
@@ -6,6 +8,7 @@ module AgileProxy
6
8
  # This server is responsible for handling or passing through a request, depending
7
9
  # on if it has a matching 'Request Specification'
8
10
  class RequestSpec
11
+
9
12
  # Starts the server
10
13
  def self.start
11
14
  new.start
@@ -15,16 +18,23 @@ module AgileProxy
15
18
  end
16
19
  # Starts the server
17
20
  def start
18
- @signature = EM.start_server('127.0.0.1', AgileProxy.config.proxy_port, ProxyConnection) do |p|
19
- p.handler = @request_handler
20
- end
21
+ #
22
+ # The API runner
23
+ runner = ::Goliath::Proxy::Runner.new([], nil)
24
+ runner.address = '127.0.0.1'
25
+ runner.port = AgileProxy.config.proxy_port
26
+ app = @request_handler
27
+ runner.app = app
28
+ runner.run
21
29
  self
30
+
22
31
  end
23
32
  # The port the server is running on
24
33
  # @return [Integer] The port the server is running on
25
34
  def port
26
- Socket.unpack_sockaddr_in(EM.get_sockname(@signature)).first
35
+ return AgileProxy.config.proxy_port
27
36
  end
37
+ private
28
38
  end
29
39
  end
30
40
  end
@@ -1,6 +1,6 @@
1
1
  require 'rack'
2
- require 'thin'
3
-
2
+ require 'goliath/api'
3
+ require 'goliath/runner'
4
4
  module AgileProxy
5
5
  module Servers
6
6
  #
@@ -17,21 +17,17 @@ module AgileProxy
17
17
  # @param server_host [String] The host for the server to run on
18
18
  # @param server_port [Integer] The port for the server to run on
19
19
  def start(server_host, server_port, static_dirs = [])
20
- # The sinatra web server
21
- dispatch = Rack::Builder.app do
20
+
21
+ runner = ::Goliath::Runner.new([], nil)
22
+ runner.address = server_host
23
+ runner.port = server_port
24
+ runner.app = ::Goliath::Rack::Builder.app do
22
25
  use Rack::Static, root: File.join(ROOT, 'assets'), urls: static_dirs, index: 'index.html' unless static_dirs.empty?
23
26
  map '/' do
24
27
  run ::AgileProxy::StubHandler.new
25
28
  end
26
29
  end
27
- # Start the web server.
28
- ::Rack::Server.start(
29
- app: dispatch,
30
- server: 'thin',
31
- Host: server_host,
32
- Port: server_port,
33
- signals: false
34
- )
30
+ runner.run
35
31
  end
36
32
  end
37
33
  end
@@ -2,5 +2,5 @@
2
2
  #
3
3
  # The Agile Proxy module is a common namespace for all classes / sub modules.
4
4
  module AgileProxy
5
- VERSION = '0.1.20'
5
+ VERSION = '0.1.21'
6
6
  end
@@ -10,6 +10,7 @@ RSpec.configure do |config|
10
10
  config.before :all, :type => :integration do
11
11
  start_test_servers
12
12
  start_proxy_server
13
+ debug_me = true
13
14
  end
14
15
 
15
16
  end
@@ -1,23 +1,80 @@
1
- require 'eventmachine'
2
- require 'thin'
3
1
  require 'faraday'
4
2
  require 'agile_proxy/cli'
3
+ require 'socket'
4
+
5
+
5
6
 
6
- module Thin
7
- module Backends
8
- class TcpServer
9
- def get_port
10
- # seriously, eventmachine, how hard does getting a port have to be?
11
- Socket.unpack_sockaddr_in(EM.get_sockname(@signature)).first
12
- end
13
- end
14
- end
15
- end
16
7
 
17
8
  module AgileProxy
18
9
  module TestServer
10
+ class DummyApi
11
+ def response(env)
12
+ [200, {}, "hello!"]
13
+ end
14
+ end
15
+ class Server
16
+ attr_accessor :server_port
17
+ def initialize(world)
18
+ @world = world
19
+ at_exit do
20
+ cleanup
21
+ end
22
+ #Thin::Logging.silent = true
23
+ end
24
+ def pids
25
+ @pids ||= []
26
+ end
27
+ def cleanup
28
+ until pids.empty?
29
+ begin
30
+ Process.kill('INT', pids.pop);
31
+ rescue Errno::ESRCH
32
+ #Do nothing
33
+ end
34
+ end
35
+ end
36
+ def available_port(qty = 1)
37
+ # use Addrinfo
38
+ results = []
39
+ sockets_opened = []
40
+ while results.length < qty
41
+ socket = Socket.new(:INET, :STREAM, 0)
42
+ socket.bind(Addrinfo.tcp("127.0.0.1", 0))
43
+ port = socket.local_address.ip_port
44
+ results.push port unless results.include? port
45
+ sockets_opened.push socket
46
+ end
47
+ sockets_opened.each do |socket|
48
+ socket.close
49
+ end
50
+ results
51
+ end
52
+
53
+ def ruby
54
+ RbConfig.ruby
55
+ end
56
+ def start_test_servers
57
+ ports = available_port(3)
58
+ puts "Starting test server on #{ports[0]}"
59
+ pids.push spawn(ruby, "echo_server.rb", '--address', 'localhost', '--port', "#{ports[0]}")
60
+ puts "Starting test server on #{ports[1]}"
61
+ pids.push spawn(ruby, "echo_server.rb", '--address', 'localhost', '--port', "#{ports[1]}", '--ssl')
62
+ puts "Starting test server on #{ports[2]}"
63
+ pids.push spawn({'STATUS_CODE' => '500'}, ruby, "echo_server.rb", '--address', 'localhost', '--port', "#{ports[2]}")
64
+ @world.instance_eval do
65
+ @http_url = "http://localhost:#{ports.shift}"
66
+ @https_url = "https://localhost:#{ports.shift}"
67
+ @error_url = "http://localhost:#{ports.shift}"
68
+ @http_url_no_proxy = "http://localhost:#{server_port}"
69
+ @https_url_no_proxy = "https://localhost:#{server_port}"
70
+ end
71
+ end
72
+
73
+
74
+ end
75
+
19
76
  def initialize(rspecParams=nil)
20
- Thin::Logging.silent = true
77
+
21
78
  end
22
79
  def proxy_port
23
80
  3101
@@ -29,66 +86,20 @@ module AgileProxy
29
86
  3022
30
87
  end
31
88
 
32
- def start_test_servers
33
- q = Queue.new
34
- Thread.new do
35
- EM.run do
36
- echo = echo_app_setup
37
-
38
- http_server = start_server(echo)
39
- q.push http_server.backend.get_port
40
89
 
41
- https_server = start_server(echo, true)
42
- q.push https_server.backend.get_port
43
-
44
- echo_error = echo_app_setup(500)
45
- error_server = start_server(echo_error)
46
- q.push error_server.backend.get_port
47
- end
48
- end
49
-
50
- @http_url = "http://localhost:#{q.pop}"
51
- @https_url = "https://localhost:#{q.pop}"
52
- @error_url = "http://localhost:#{q.pop}"
53
- @http_url_no_proxy = "http://localhost:#{server_port}"
54
- @https_url_no_proxy = "https://localhost:#{server_port}"
90
+ def start_test_servers
91
+ @test_servers = Server.new(self)
92
+ @test_servers.server_port = server_port
93
+ @test_servers.start_test_servers
55
94
  end
56
95
 
57
96
  def start_proxy_server
58
97
  Thread.new do
59
98
  cli = Cli.start(['start', proxy_port.to_s, server_port.to_s, api_port.to_s, '--env', 'test'])
60
99
  end
61
- sleep 1
100
+ sleep 10
62
101
  end
63
102
 
64
- def echo_app_setup(response_code = 200)
65
- counter = 0
66
- proc do |env|
67
- req_body = env['rack.input'].read
68
- request_info = "#{env['REQUEST_METHOD']} #{env['PATH_INFO']}"
69
- res_body = request_info
70
- res_body += "\n#{req_body}" unless req_body.empty?
71
- counter += 1
72
- [
73
- response_code,
74
- { 'HTTP-X-EchoServer' => request_info,
75
- 'HTTP-X-EchoCount' => "#{counter}" },
76
- [res_body]
77
- ]
78
- end
79
- end
80
103
 
81
- def start_server(echo, ssl = false)
82
- http_server = Thin::Server.new '127.0.0.1', 0, echo
83
- if ssl
84
- http_server.ssl = true
85
- http_server.ssl_options = {
86
- private_key_file: File.expand_path('../../fixtures/test-server.key', __FILE__),
87
- cert_chain_file: File.expand_path('../../fixtures/test-server.crt', __FILE__)
88
- }
89
- end
90
- http_server.start
91
- http_server
92
- end
93
104
  end
94
105
  end