agile-proxy-jruby 0.1.25-jruby

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +7 -0
  2. data/.bowerrc +3 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +2 -0
  5. data/.rubocop.yml +36 -0
  6. data/.travis.yml +10 -0
  7. data/Gemfile +4 -0
  8. data/Guardfile +20 -0
  9. data/LICENSE +22 -0
  10. data/README.md +131 -0
  11. data/Rakefile +15 -0
  12. data/agile-proxy.gemspec +60 -0
  13. data/assets/index.html +39 -0
  14. data/assets/ui/app/AgileProxyApi.js +31 -0
  15. data/assets/ui/app/app.js +1 -0
  16. data/assets/ui/app/controller/Stubs.js +64 -0
  17. data/assets/ui/app/controller/main.js +12 -0
  18. data/assets/ui/app/directive/AppEnhancedFormElement.js +21 -0
  19. data/assets/ui/app/directive/AppFor.js +16 -0
  20. data/assets/ui/app/directive/AppResponseEditor.js +54 -0
  21. data/assets/ui/app/model/RequestSpec.js +6 -0
  22. data/assets/ui/app/routes.js +11 -0
  23. data/assets/ui/app/service/Dialog.js +49 -0
  24. data/assets/ui/app/service/DomId.js +10 -0
  25. data/assets/ui/app/service/Error.js +7 -0
  26. data/assets/ui/app/service/Stub.js +36 -0
  27. data/assets/ui/app/view/404.html +2 -0
  28. data/assets/ui/app/view/dialog/error.html +10 -0
  29. data/assets/ui/app/view/dialog/yesNo.html +8 -0
  30. data/assets/ui/app/view/responses/editForm.html +78 -0
  31. data/assets/ui/app/view/status.html +1 -0
  32. data/assets/ui/app/view/stubs.html +19 -0
  33. data/assets/ui/app/view/stubs/edit.html +58 -0
  34. data/assets/ui/css/main.css +3 -0
  35. data/bin/agile_proxy +4 -0
  36. data/bower.json +27 -0
  37. data/config.yml +6 -0
  38. data/db.yml +10 -0
  39. data/db/migrations/20140818110800_create_users.rb +9 -0
  40. data/db/migrations/20140818134700_create_applications.rb +10 -0
  41. data/db/migrations/20140818135200_create_request_specs.rb +13 -0
  42. data/db/migrations/20140821115300_create_responses.rb +14 -0
  43. data/db/migrations/20140823082900_add_method_to_request_specs.rb +7 -0
  44. data/db/migrations/20140823083900_rename_request_spec_columns.rb +8 -0
  45. data/db/migrations/20141031072100_add_url_type_to_request_specs.rb +8 -0
  46. data/db/migrations/20141105125600_add_conditions_to_request_specs.rb +7 -0
  47. data/db/migrations/20141106083100_add_username_and_password_to_applications.rb +8 -0
  48. data/db/migrations/20141119143800_add_record_to_applications.rb +7 -0
  49. data/db/migrations/20141119174300_create_recordings.rb +18 -0
  50. data/db/migrations/20150221152500_add_record_requests_to_request_specs.rb +7 -0
  51. data/db/schema.rb +78 -0
  52. data/db/seed.rb +26 -0
  53. data/echo_server.rb +19 -0
  54. data/examples/README.md +1 -0
  55. data/examples/facebook_api.html +59 -0
  56. data/examples/tumblr_api.html +22 -0
  57. data/lib/agile_proxy.rb +8 -0
  58. data/lib/agile_proxy/api/applications.rb +77 -0
  59. data/lib/agile_proxy/api/recordings.rb +52 -0
  60. data/lib/agile_proxy/api/request_spec_recordings.rb +52 -0
  61. data/lib/agile_proxy/api/request_specs.rb +86 -0
  62. data/lib/agile_proxy/api/root.rb +45 -0
  63. data/lib/agile_proxy/cli.rb +116 -0
  64. data/lib/agile_proxy/config.rb +66 -0
  65. data/lib/agile_proxy/handlers/handler.rb +43 -0
  66. data/lib/agile_proxy/handlers/proxy_handler.rb +111 -0
  67. data/lib/agile_proxy/handlers/request_handler.rb +75 -0
  68. data/lib/agile_proxy/handlers/stub_handler.rb +146 -0
  69. data/lib/agile_proxy/mitm.crt +22 -0
  70. data/lib/agile_proxy/mitm.key +27 -0
  71. data/lib/agile_proxy/model/application.rb +20 -0
  72. data/lib/agile_proxy/model/recording.rb +17 -0
  73. data/lib/agile_proxy/model/request_spec.rb +48 -0
  74. data/lib/agile_proxy/model/response.rb +51 -0
  75. data/lib/agile_proxy/model/user.rb +17 -0
  76. data/lib/agile_proxy/proxy_connection.rb +112 -0
  77. data/lib/agile_proxy/rack/get_only_cache.rb +30 -0
  78. data/lib/agile_proxy/route.rb +106 -0
  79. data/lib/agile_proxy/router.rb +99 -0
  80. data/lib/agile_proxy/server.rb +119 -0
  81. data/lib/agile_proxy/servers/api.rb +40 -0
  82. data/lib/agile_proxy/servers/request_spec.rb +40 -0
  83. data/lib/agile_proxy/servers/request_spec_direct.rb +35 -0
  84. data/lib/agile_proxy/version.rb +6 -0
  85. data/load_proxy.js +39 -0
  86. data/log/.gitkeep +0 -0
  87. data/spec/common_helper.rb +32 -0
  88. data/spec/fixtures/example_static_file.html +1 -0
  89. data/spec/fixtures/test-server.crt +15 -0
  90. data/spec/fixtures/test-server.key +15 -0
  91. data/spec/integration/helpers/request_spec_helper.rb +84 -0
  92. data/spec/integration/specs/lib/server_spec.rb +474 -0
  93. data/spec/integration_spec_helper.rb +16 -0
  94. data/spec/spec_helper.rb +39 -0
  95. data/spec/support/test_server.rb +105 -0
  96. data/spec/unit/agile_proxy/api/applications_spec.rb +102 -0
  97. data/spec/unit/agile_proxy/api/common_helper.rb +31 -0
  98. data/spec/unit/agile_proxy/api/recordings_spec.rb +115 -0
  99. data/spec/unit/agile_proxy/api/request_spec_recordings_spec.rb +119 -0
  100. data/spec/unit/agile_proxy/api/request_specs_spec.rb +159 -0
  101. data/spec/unit/agile_proxy/handlers/handler_spec.rb +8 -0
  102. data/spec/unit/agile_proxy/handlers/proxy_handler_spec.rb +138 -0
  103. data/spec/unit/agile_proxy/handlers/request_handler_spec.rb +76 -0
  104. data/spec/unit/agile_proxy/handlers/stub_handler_spec.rb +177 -0
  105. data/spec/unit/agile_proxy/model/recording_spec.rb +0 -0
  106. data/spec/unit/agile_proxy/model/request_spec_spec.rb +45 -0
  107. data/spec/unit/agile_proxy/model/response_spec.rb +38 -0
  108. data/spec/unit/agile_proxy/server_spec.rb +91 -0
  109. data/spec/unit/agile_proxy/servers/api_spec.rb +35 -0
  110. data/spec/unit/agile_proxy/servers/request_spec_direct_spec.rb +51 -0
  111. data/spec/unit/agile_proxy/servers/request_spec_spec.rb +35 -0
  112. metadata +736 -0
@@ -0,0 +1,51 @@
1
+ require 'flavour_saver'
2
+ require 'flavour_saver/runtime'
3
+ module AgileProxy
4
+ #
5
+ # = The associated response for the RequestSpec
6
+ #
7
+ # An instance of this class is expected to be stored alongside every RequestSpec.
8
+ #
9
+ # It is responsible for the following :-
10
+ #
11
+ # 1. Retrieving response
12
+ # 2. Persisting responses
13
+ # 3. Providing a 'rack' ouput of the response
14
+ # 4. Convenient setters for code, body and content_type
15
+ # 5. Template parsing
16
+ class Response < ActiveRecord::Base
17
+ PROTECTED_HEADERS = ['Content-Type']
18
+ has_many :request_specs
19
+ serialize :headers, JSON
20
+ # A convenient setter for the content_type within the header
21
+ # @param val [String] The content type
22
+ def content_type=(val)
23
+ write_attribute(:content_type, val)
24
+ headers.merge!('Content-Type' => val)
25
+ val
26
+ end
27
+ # Provides the response as a 'rack' response
28
+ #
29
+ # If the response is a template (by specifying is_template as true), the output will
30
+ # have its template values parsed and replaced with
31
+ # data from the input_params, input_headers and input_body
32
+ # Otherwise, the body of the output is sent as is.
33
+ # @param input_params [Hash] The input parameters as a hash
34
+ # @param _input_headers [Hash] The input headers as a hash
35
+ # @param _input_body [String] The input body
36
+ # @return [Array] A 'rack' response array (status, headers, body)
37
+ def to_rack(input_params, _input_headers, _input_body)
38
+ output_headers = headers.clone
39
+ output_headers.merge! 'Cache-Control' => 'no-store'
40
+ output_content = content
41
+ output_status_code = status_code
42
+ if is_template
43
+ data = OpenStruct.new input_params
44
+ template = Tilt['handlebars'].new { output_content }
45
+ output_content = template.render data
46
+ end
47
+ EventMachine::Synchrony.sleep(delay) if delay > 0
48
+ [output_status_code, output_headers, [output_content]]
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,17 @@
1
+ require_relative 'application'
2
+ require 'active_record'
3
+ module AgileProxy
4
+ #
5
+ # = An API User
6
+ #
7
+ # The API access to the system is multi user in that each user
8
+ # can have many applications and each application can have many stubs etc...
9
+ #
10
+ # This class is responsible for :-
11
+ # 1. Retrieving users from storage
12
+ # 2. Persisting users to storage
13
+ # 3. Providing a list of applications that the user owns
14
+ class User < ActiveRecord::Base
15
+ has_many :applications
16
+ end
17
+ end
@@ -0,0 +1,112 @@
1
+ require 'uri'
2
+ require 'eventmachine'
3
+ require 'stringio'
4
+ require 'rack'
5
+ require 'goliath/request'
6
+ require 'goliath/env'
7
+
8
+ module AgileProxy
9
+ #
10
+ # = The Proxy Connection
11
+ #
12
+ # This class is the event machine connection used by the proxy. Every request creates a new instance of this
13
+ class ProxyConnection < Goliath::Connection
14
+ def logger
15
+ ::AgileProxy.config.logger
16
+ end
17
+ def post_init
18
+ super
19
+ #@proxy_parser = Http::Parser.new(self)
20
+ @proxy_parser = Http::Parser.new
21
+ end
22
+
23
+ def receive_data(data)
24
+ #@proxy_parser << data
25
+ @parser << data
26
+ end
27
+
28
+ def on_message_begin
29
+ @headers = nil
30
+ @body = ''
31
+ end
32
+
33
+ def on_headers_complete(headers)
34
+ @headers = headers
35
+ end
36
+
37
+ def on_body(chunk)
38
+ @body << chunk
39
+ end
40
+
41
+ def on_message_complete
42
+ if @proxy_parser.http_method == 'CONNECT'
43
+ restart_with_ssl(@proxy_parser.request_url)
44
+ else
45
+ if @ssl
46
+ uri = URI.parse(@proxy_parser.request_url)
47
+ @url = "https://#{@ssl}#{[uri.path, uri.query].compact.join('?')}"
48
+ else
49
+ @url = @proxy_parser.request_url
50
+ end
51
+ handle_request
52
+ end
53
+ end
54
+
55
+
56
+ protected
57
+
58
+ def restart_with_ssl(url)
59
+ @ssl = url
60
+ @proxy_parser = Http::Parser.new(self)
61
+ @original_headers = @headers.clone
62
+ send_data("HTTP/1.0 200 Connection established\r\nProxy-agent: Http-Flexible-Proxy/0.0.0\r\n\r\n")
63
+ start_tls(
64
+ private_key_file: File.expand_path('../mitm.key', __FILE__),
65
+ cert_chain_file: File.expand_path('../mitm.crt', __FILE__)
66
+ )
67
+ end
68
+
69
+ def handle_request
70
+ EM.synchrony do
71
+ request = ::Goliath::Request.new(handler, self, env)
72
+ request.set_deferred_status :succeeded
73
+ request.process
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def env
80
+ return @__env if @__env
81
+ fake_input_buffer = StringIO.new(@body)
82
+ fake_error_buffer = StringIO.new
83
+ url_parsed = URI.parse(@url)
84
+ @__env = ::Goliath::Env.new
85
+ @__env.merge!({
86
+ 'rack.input' => Rack::Lint::InputWrapper.new(fake_input_buffer),
87
+ 'rack.errors' => Rack::Lint::ErrorWrapper.new(fake_error_buffer),
88
+ 'REQUEST_METHOD' => @proxy_parser.http_method,
89
+ 'REQUEST_PATH' => url_parsed.path,
90
+ 'PATH_INFO' => url_parsed.path,
91
+ 'QUERY_STRING' => url_parsed.query || '',
92
+ 'REQUEST_URI' => url_parsed.path + (url_parsed.query || ''),
93
+ 'rack.url_scheme' => url_parsed.scheme,
94
+ 'CONTENT_LENGTH' => @body.length,
95
+ 'SERVER_NAME' => url_parsed.host,
96
+ 'SERVER_PORT' => url_parsed.port,
97
+ 'rack.logger' => logger
98
+
99
+
100
+ })
101
+ @headers.merge(@original_headers || {}).each do |name, value|
102
+ converted_name = "HTTP_#{name.gsub(/-/, '_').upcase}"
103
+ @__env[converted_name] = value
104
+ end
105
+ @__env['CONTENT_TYPE'] = @__env.delete('HTTP_CONTENT_TYPE') if @__env.key?('HTTP_CONTENT_TYPE')
106
+ @__env['CONTENT_LENGTH'] = @__env.delete('HTTP_CONTENT_LENGTH') if @__env.key?('HTTP_CONTENT_LENGTH')
107
+ @__env
108
+ end
109
+
110
+
111
+ end
112
+ end
@@ -0,0 +1,30 @@
1
+ require 'rack-cache'
2
+ require 'action_dispatch/http/request'
3
+ module AgileProxy
4
+ module Rack
5
+ class GetOnlyCache
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+ def call(env)
10
+ force_caching(env)
11
+ request = ::ActionDispatch::Request.new(env)
12
+ if request.request_method_symbol == :get
13
+ cache_app.call(env)
14
+ else
15
+ @app.call(env)
16
+ end
17
+ end
18
+
19
+ private
20
+ def force_caching(env)
21
+ env.delete 'HTTP_PRAGMA' if env['HTTP_PRAGMA'] == 'no-cache'
22
+ env.delete 'HTTP_CACHE_CONTROL' if env['HTTP_CACHE_CONTROL'] == 'no-cache'
23
+ end
24
+ def cache_app
25
+ @cache_app ||= ::Rack::Cache.new(@app)
26
+ end
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,106 @@
1
+ module AgileProxy
2
+ #
3
+ # An instance of this class represents a route within the system.
4
+ #
5
+ class Route
6
+ attr_accessor :request_method, :pattern, :app, :constraints, :name
7
+
8
+ PATH_INFO = 'PATH_INFO'.freeze
9
+ ROUTE_PARAMS = 'rack.route_params'.freeze
10
+ QUERY_STRING = 'QUERY_STRING'.freeze
11
+ FORM_HASH = 'rack.request.form_hash'.freeze
12
+ REQUEST_METHOD = 'REQUEST_METHOD'.freeze
13
+ HEAD = 'HEAD'.freeze
14
+ GET = 'GET'.freeze
15
+ POST = 'POST'.freeze
16
+ PUT = 'PUT'.freeze
17
+ DELETE = 'DELETE'.freeze
18
+
19
+ DEFAULT_WILDCARD_NAME = :paths
20
+ WILDCARD_PATTERN = /\/\*(.*)/.freeze
21
+ NAMED_SEGMENTS_PATTERN = /\/:([^$\/]+)/.freeze
22
+ NAMED_SEGMENTS_REPLACEMENT_PATTERN = /\/:([^$\/]+)/.freeze
23
+ DOT = '.'.freeze
24
+
25
+ def initialize(request_method, pattern, app, options = {})
26
+ fail ArgumentError, 'pattern cannot be blank' if pattern.to_s.strip.empty?
27
+ fail ArgumentError, 'app must be callable' unless app.respond_to?(:call)
28
+ @request_method = request_method
29
+ @pattern = pattern
30
+ @app = app
31
+ @constraints = options && options[:constraints]
32
+ @name = options && options[:as]
33
+ end
34
+
35
+ def regexp
36
+ @regexp ||= compile
37
+ end
38
+
39
+ def compile
40
+ pattern_match = pattern.match(WILDCARD_PATTERN)
41
+ src = if pattern_match
42
+ @wildcard_name = if pattern_match[1].to_s.strip.empty?
43
+ DEFAULT_WILDCARD_NAME
44
+ else
45
+ pattern_match[1].to_sym
46
+ end
47
+ pattern.gsub(WILDCARD_PATTERN, '(?:/(.*)|)')
48
+ else
49
+ pattern_match = pattern.match(NAMED_SEGMENTS_PATTERN)
50
+ p = if pattern_match
51
+ pattern.gsub(NAMED_SEGMENTS_REPLACEMENT_PATTERN, '/(?<\1>[^.$/]+)')
52
+ else
53
+ pattern
54
+ end
55
+ p + '(?:\.(?<format>.*))?'
56
+ end
57
+ Regexp.new("\\A#{src}\\Z")
58
+ end
59
+
60
+ def match(env)
61
+ request_method = env[REQUEST_METHOD]
62
+ request_method = GET if request_method == HEAD
63
+ path = env[PATH_INFO]
64
+ qs = env[QUERY_STRING]
65
+ return nil unless request_method == self.request_method
66
+ fail ArgumentError, 'path is required' if path.to_s.strip.empty?
67
+ path_match = path.match(regexp)
68
+ return unless path_match
69
+ params = if @wildcard_name
70
+ { @wildcard_name => path_match[1].to_s.split('/') }
71
+ else
72
+ Hash[path_match.names.map(&:to_sym).zip(path_match.captures)]
73
+ end
74
+ params.merge!(::Rack::Utils.parse_nested_query(qs).symbolize_keys) unless qs.nil? || qs.empty?
75
+ params.merge! env[FORM_HASH] if env.key? FORM_HASH
76
+ params.delete(:format) if params.key?(:format) && params[:format].nil?
77
+
78
+ params if meets_constraints(params)
79
+ end
80
+
81
+ def meets_constraints(params)
82
+ if constraints
83
+ constraints.each do |param, constraint|
84
+ unless params.symbolize_keys[param.to_sym].to_s.match(constraint)
85
+ return false
86
+ end
87
+ end
88
+ end
89
+ true
90
+ end
91
+
92
+ def eql?(other)
93
+ other.is_a?(self.class) &&
94
+ other.request_method == request_method &&
95
+ other.pattern == pattern &&
96
+ other.app == app &&
97
+ other.constraints == constraints
98
+ end
99
+
100
+ alias_method :==, :eql?
101
+
102
+ def hash
103
+ request_method.hash ^ pattern.hash ^ app.hash ^ constraints.hash
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,99 @@
1
+ require 'agile_proxy/route'
2
+
3
+ module AgileProxy
4
+ #
5
+ # A rack router used for selecting a 'request spec' from a shortlist
6
+ #
7
+ class Router
8
+ VERSION = '0.4.0'
9
+
10
+ HEAD = 'HEAD'.freeze
11
+ GET = 'GET'.freeze
12
+ POST = 'POST'.freeze
13
+ PUT = 'PUT'.freeze
14
+ DELETE = 'DELETE'.freeze
15
+ REQUEST_METHOD = 'REQUEST_METHOD'.freeze
16
+ PATH_INFO = 'PATH_INFO'.freeze
17
+ ROUTE_PARAMS = 'rack.route_params'.freeze
18
+ QUERY_STRING = 'QUERY_STRING'.freeze
19
+ FORM_HASH = 'rack.request.form_hash'.freeze
20
+
21
+ def initialize(&block)
22
+ @named_routes = {}
23
+ routes(&block)
24
+ end
25
+
26
+ def [](route_name)
27
+ @named_routes[route_name]
28
+ end
29
+
30
+ def routes(&block)
31
+ instance_eval(&block) if block
32
+ @routes
33
+ end
34
+
35
+ def get(route_spec)
36
+ route(GET, route_spec)
37
+ end
38
+
39
+ def post(route_spec)
40
+ route(POST, route_spec)
41
+ end
42
+
43
+ def put(route_spec)
44
+ route(PUT, route_spec)
45
+ end
46
+
47
+ def delete(route_spec)
48
+ route(DELETE, route_spec)
49
+ end
50
+
51
+ def route(method, route_spec)
52
+ route = Route.new(
53
+ method,
54
+ route_spec.first.first,
55
+ route_spec.first.last,
56
+ route_spec.reject { |k, _| k == route_spec.first.first }
57
+ )
58
+ @routes ||= []
59
+ @routes << route
60
+ if route_spec && route_spec[:as]
61
+ # Using ||= so the first route with that name will be returned
62
+ @named_routes[route_spec[:as].to_sym] ||= route_spec.first.first
63
+ end
64
+ route
65
+ end
66
+
67
+ def call(env)
68
+ app = match(env)
69
+ if app
70
+ app.call(env)
71
+ else
72
+ not_found(env)
73
+ end
74
+ end
75
+
76
+ def match(env)
77
+ routes.each do |route|
78
+ params = route.match(env)
79
+ if params
80
+ env[ROUTE_PARAMS] = params
81
+ return route.app
82
+ end
83
+ end
84
+ nil
85
+ end
86
+
87
+ def not_found(env)
88
+ body = "<h1>Not Found</h1><p>No route matches #{env[REQUEST_METHOD]} #{env[PATH_INFO]}</p>"
89
+ [
90
+ 404,
91
+ {
92
+ 'Content-Type' => 'text/html',
93
+ 'Content-Length' => body.length.to_s
94
+ },
95
+ [body]
96
+ ]
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,119 @@
1
+ require 'active_record'
2
+ require 'yaml'
3
+ require 'cgi'
4
+ require 'uri'
5
+ require 'eventmachine'
6
+ require 'grape'
7
+ require 'agile_proxy/api/root'
8
+ require 'agile_proxy/servers/api'
9
+ require 'agile_proxy/servers/request_spec'
10
+ require 'agile_proxy/servers/request_spec_direct'
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
+
27
+ module AgileProxy
28
+ #
29
+ # This class is responsible for controlling the underlying proxy and web servers
30
+ #
31
+ class Server
32
+ ROOT = File.expand_path '../../', File.dirname(__FILE__)
33
+ extend Forwardable
34
+ attr_reader :request_handler
35
+
36
+ def_delegators :request_handler, :reset_cache, :restore_cache, :handle_request
37
+
38
+ def initialize
39
+ environment = AgileProxy.config.environment
40
+ dbconfig = YAML.load(File.read(AgileProxy.config.database_config_file)).with_indifferent_access
41
+ ActiveRecord::Base.configurations = dbconfig
42
+ ActiveRecord::Base.establish_connection dbconfig[environment.to_s]
43
+ end
44
+
45
+ # Starts the proxy and web servers
46
+ def start
47
+ main_loop
48
+ end
49
+
50
+ # The url that the proxy server is running on
51
+ # @return [String] The URL
52
+ def url
53
+ "http://#{host}:#{port}"
54
+ end
55
+
56
+ # The url that the web server can be accessed from
57
+ # @return [String] The URL
58
+ def webserver_url
59
+ "http://#{webserver_host}:#{webserver_port}"
60
+ end
61
+
62
+ # The url that the direct web server can be accessed from
63
+ # @return [String] The URL
64
+ def server_url
65
+ "http://#{server_host}:#{server_port}"
66
+ end
67
+
68
+ # The host that the proxy server is running on
69
+ # @return [String] The host
70
+ def host
71
+ 'localhost'
72
+ end
73
+
74
+ # The port that the proxy server is running on
75
+ # @return [String] The port
76
+ def port
77
+ @request_spec_server.port
78
+ end
79
+
80
+ # The host that the webserver is running on
81
+ # @return [String] The host
82
+ def webserver_host
83
+ AgileProxy.config.webserver_host
84
+ end
85
+
86
+ # The port that the webserver is running on
87
+ # @return [String] The port
88
+ def webserver_port
89
+ AgileProxy.config.webserver_port
90
+ end
91
+
92
+ # The host that the direct server is running on
93
+ # @return [String] The host
94
+ def server_host
95
+ AgileProxy.config.server_host
96
+ end
97
+
98
+ # The port that the direct server is running on
99
+ # @return [String] The port
100
+ def server_port
101
+ AgileProxy.config.server_port
102
+ end
103
+
104
+ protected
105
+
106
+ def main_loop
107
+ EM.run do
108
+ EM.error_handler do |e|
109
+ puts e.class.name, e
110
+ puts e.backtrace.join("\n")
111
+ end
112
+ AgileProxy::Servers::Api.start(webserver_host, webserver_port)
113
+ AgileProxy::Servers::RequestSpecDirect.start(server_host, server_port)
114
+ @request_spec_server = AgileProxy::Servers::RequestSpec.start enable_cache: AgileProxy.config.enable_cache
115
+ AgileProxy.log(:info, "agile-proxy: Proxy listening on #{url}, API webserver listening on #{webserver_url} and Direct webserver listening on #{server_url}")
116
+ end
117
+ end
118
+ end
119
+ end