agile-proxy 0.1.21 → 0.1.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -2
- data/README.md +1 -0
- data/agile-proxy.gemspec +8 -14
- data/lib/agile_proxy/handlers/request_handler.rb +1 -2
- data/lib/agile_proxy/handlers/stub_handler.rb +1 -0
- data/lib/agile_proxy/model/recording.rb +0 -1
- data/lib/agile_proxy/proxy_connection.rb +28 -27
- data/lib/agile_proxy/server.rb +1 -15
- data/lib/agile_proxy/servers/api.rb +11 -10
- data/lib/agile_proxy/servers/request_spec.rb +4 -14
- data/lib/agile_proxy/servers/request_spec_direct.rb +12 -8
- data/lib/agile_proxy/version.rb +1 -1
- data/spec/integration_spec_helper.rb +0 -1
- data/spec/support/test_server.rb +64 -75
- data/spec/unit/agile_proxy/servers/api_spec.rb +5 -9
- data/spec/unit/agile_proxy/servers/request_spec_direct_spec.rb +5 -13
- data/spec/unit/agile_proxy/servers/request_spec_spec.rb +13 -16
- metadata +126 -27
- data/echo_server.rb +0 -19
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cdc83345bdd428e0b53171381e809cd739281a32
|
4
|
+
data.tar.gz: 52dc13eeb368e9d19cb2f3cc1f2248d6320a573c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e10828a0c1eaf12ee379f4b4de473c5a64afd514722897561b21e2a4327a27f7d93836043ee26103eb282840bd9c1a92ff1a0532566c5c9423abe9956f4f29ca
|
7
|
+
data.tar.gz: f287eb594c2ba7d69e3b19d640bbde4a1beec400cecb40d5c4ee17b5d12532019e7cf32ba767cba245338aa5c41a1d9ad5bd10ec3ca3a2d8734fa07000e74eaa
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -123,4 +123,5 @@ 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
125
|
v0.1.21 - Switched to goliath instead of thin. The gem now installs under jruby as well as other platforms.
|
126
|
+
v0.1.22 - Reverted 0.1.21 - Integration tests worked fine, but failed in real world scenario - never ending responses from stubs
|
126
127
|
|
data/agile-proxy.gemspec
CHANGED
@@ -21,9 +21,11 @@ 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'
|
24
25
|
gem.add_development_dependency 'guard', '~> 2.6', '>= 2.6.1'
|
25
26
|
gem.add_development_dependency 'rb-inotify', '~> 0.9', '>= 0.9.5'
|
26
27
|
gem.add_development_dependency 'cucumber', '~> 1.3', '>= 1.3.17'
|
28
|
+
gem.add_development_dependency 'airborne', '~> 0.1', '>= 0.1.10'
|
27
29
|
gem.add_development_dependency 'rest-client', '~> 1.7', '>= 1.7.2'
|
28
30
|
gem.add_development_dependency 'require_all', '~> 1.3', '>= 1.3.2'
|
29
31
|
gem.add_development_dependency 'faker', '~> 1.2', '>= 1.2.0'
|
@@ -33,24 +35,16 @@ Gem::Specification.new do |gem|
|
|
33
35
|
gem.add_runtime_dependency 'eventmachine', '~> 1.0', '>= 1.0.3'
|
34
36
|
gem.add_runtime_dependency 'em-synchrony', '~> 1.0', '>= 1.0.3'
|
35
37
|
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'
|
36
42
|
gem.add_runtime_dependency 'grape', '~> 0.10', '>= 0.10.1'
|
37
43
|
gem.add_runtime_dependency 'activerecord', '~> 4.2', '>= 4.2.0'
|
38
|
-
|
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
|
-
|
44
|
+
gem.add_runtime_dependency 'sqlite3', '~> 1.3', '>= 1.3.10'
|
49
45
|
gem.add_runtime_dependency 'grape-kaminari', '~> 0.1', '>= 0.1.7'
|
50
46
|
gem.add_runtime_dependency 'shoulda-matchers', '2.8.0.rc2'
|
51
47
|
gem.add_runtime_dependency 'flavour_saver', '~> 0.3', '>= 0.3.4'
|
52
48
|
gem.add_runtime_dependency 'thor', '~> 0.19', '>= 0.19.1'
|
53
|
-
gem.add_runtime_dependency '
|
54
|
-
gem.add_runtime_dependency 'goliath-proxy', '~> 0.0', '>= 0.0.1'
|
55
|
-
|
49
|
+
gem.add_runtime_dependency 'rack-parser', '~> 0.6', '>= 0.6.1'
|
56
50
|
end
|
@@ -36,9 +36,8 @@ module AgileProxy
|
|
36
36
|
]
|
37
37
|
end
|
38
38
|
request_spec = env['agile_proxy.request_spec']
|
39
|
-
exclude_headers = ['@env', 'rack.errors', 'rack.logger']
|
40
39
|
if application.record_requests || (request_spec && request_spec.record_requests)
|
41
|
-
application.recordings.create request_headers: request.headers
|
40
|
+
application.recordings.create request_headers: request.headers,
|
42
41
|
request_body: body,
|
43
42
|
request_url: request.url,
|
44
43
|
request_method: request.request_method,
|
@@ -1,27 +1,24 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'eventmachine'
|
3
|
+
require 'http/parser'
|
4
|
+
require 'em-http'
|
5
|
+
require 'evma_httpserver'
|
6
|
+
require 'em-synchrony'
|
3
7
|
require 'stringio'
|
4
8
|
require 'rack'
|
5
|
-
require 'goliath/request'
|
6
|
-
require 'goliath/env'
|
7
9
|
|
8
10
|
module AgileProxy
|
9
11
|
#
|
10
12
|
# = The Proxy Connection
|
11
13
|
#
|
12
14
|
# This class is the event machine connection used by the proxy. Every request creates a new instance of this
|
13
|
-
class ProxyConnection <
|
14
|
-
|
15
|
-
::AgileProxy.config.logger
|
16
|
-
end
|
15
|
+
class ProxyConnection < EventMachine::Connection
|
16
|
+
attr_accessor :handler
|
17
17
|
def post_init
|
18
|
-
|
19
|
-
#@proxy_parser = Http::Parser.new(self)
|
20
|
-
@proxy_parser = Http::Parser.new
|
18
|
+
@parser = Http::Parser.new(self)
|
21
19
|
end
|
22
20
|
|
23
21
|
def receive_data(data)
|
24
|
-
#@proxy_parser << data
|
25
22
|
@parser << data
|
26
23
|
end
|
27
24
|
|
@@ -39,25 +36,24 @@ module AgileProxy
|
|
39
36
|
end
|
40
37
|
|
41
38
|
def on_message_complete
|
42
|
-
if @
|
43
|
-
restart_with_ssl(@
|
39
|
+
if @parser.http_method == 'CONNECT'
|
40
|
+
restart_with_ssl(@parser.request_url)
|
44
41
|
else
|
45
42
|
if @ssl
|
46
|
-
uri = URI.parse(@
|
43
|
+
uri = URI.parse(@parser.request_url)
|
47
44
|
@url = "https://#{@ssl}#{[uri.path, uri.query].compact.join('?')}"
|
48
45
|
else
|
49
|
-
@url = @
|
46
|
+
@url = @parser.request_url
|
50
47
|
end
|
51
48
|
handle_request
|
52
49
|
end
|
53
50
|
end
|
54
51
|
|
55
|
-
|
56
52
|
protected
|
57
53
|
|
58
54
|
def restart_with_ssl(url)
|
59
55
|
@ssl = url
|
60
|
-
@
|
56
|
+
@parser = Http::Parser.new(self)
|
61
57
|
@original_headers = @headers.clone
|
62
58
|
send_data("HTTP/1.0 200 Connection established\r\nProxy-agent: Http-Flexible-Proxy/0.0.0\r\n\r\n")
|
63
59
|
start_tls(
|
@@ -68,9 +64,11 @@ module AgileProxy
|
|
68
64
|
|
69
65
|
def handle_request
|
70
66
|
EM.synchrony do
|
71
|
-
request = ::
|
72
|
-
request.
|
73
|
-
|
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
|
74
72
|
end
|
75
73
|
end
|
76
74
|
|
@@ -81,11 +79,10 @@ module AgileProxy
|
|
81
79
|
fake_input_buffer = StringIO.new(@body)
|
82
80
|
fake_error_buffer = StringIO.new
|
83
81
|
url_parsed = URI.parse(@url)
|
84
|
-
@__env =
|
85
|
-
@__env.merge!({
|
82
|
+
@__env = {
|
86
83
|
'rack.input' => Rack::Lint::InputWrapper.new(fake_input_buffer),
|
87
84
|
'rack.errors' => Rack::Lint::ErrorWrapper.new(fake_error_buffer),
|
88
|
-
'REQUEST_METHOD' => @
|
85
|
+
'REQUEST_METHOD' => @parser.http_method,
|
89
86
|
'REQUEST_PATH' => url_parsed.path,
|
90
87
|
'PATH_INFO' => url_parsed.path,
|
91
88
|
'QUERY_STRING' => url_parsed.query || '',
|
@@ -93,11 +90,9 @@ module AgileProxy
|
|
93
90
|
'rack.url_scheme' => url_parsed.scheme,
|
94
91
|
'CONTENT_LENGTH' => @body.length,
|
95
92
|
'SERVER_NAME' => url_parsed.host,
|
96
|
-
'SERVER_PORT' => url_parsed.port
|
97
|
-
'rack.logger' => logger
|
93
|
+
'SERVER_PORT' => url_parsed.port
|
98
94
|
|
99
|
-
|
100
|
-
})
|
95
|
+
}
|
101
96
|
@headers.merge(@original_headers || {}).each do |name, value|
|
102
97
|
converted_name = "HTTP_#{name.gsub(/-/, '_').upcase}"
|
103
98
|
@__env[converted_name] = value
|
@@ -107,6 +102,12 @@ module AgileProxy
|
|
107
102
|
@__env
|
108
103
|
end
|
109
104
|
|
110
|
-
|
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
|
111
112
|
end
|
112
113
|
end
|
data/lib/agile_proxy/server.rb
CHANGED
@@ -3,27 +3,13 @@ require 'yaml'
|
|
3
3
|
require 'cgi'
|
4
4
|
require 'uri'
|
5
5
|
require 'eventmachine'
|
6
|
+
require 'thin'
|
6
7
|
require 'grape'
|
7
8
|
require 'agile_proxy/api/root'
|
8
9
|
require 'agile_proxy/servers/api'
|
9
10
|
require 'agile_proxy/servers/request_spec'
|
10
11
|
require 'agile_proxy/servers/request_spec_direct'
|
11
12
|
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
13
|
module AgileProxy
|
28
14
|
#
|
29
15
|
# This class is responsible for controlling the underlying proxy and web servers
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'rack'
|
2
|
+
require 'thin'
|
2
3
|
require 'grape'
|
3
|
-
require 'goliath/api'
|
4
|
-
require 'goliath/runner'
|
5
4
|
require 'agile_proxy/api/root'
|
6
5
|
|
7
6
|
module AgileProxy
|
@@ -20,19 +19,21 @@ module AgileProxy
|
|
20
19
|
# @param webserver_host [String] The host for the server to run on
|
21
20
|
# @param webserver_port [Integer] The port for the server to run on
|
22
21
|
def start(webserver_host, webserver_port)
|
23
|
-
#
|
24
|
-
|
25
|
-
runner = ::Goliath::Runner.new([], nil)
|
26
|
-
runner.address = webserver_host
|
27
|
-
runner.port = webserver_port
|
28
|
-
runner.app = ::Goliath::Rack::Builder.app do
|
22
|
+
# The sinatra web server
|
23
|
+
dispatch = Rack::Builder.app do
|
29
24
|
use Rack::Static, root: File.join(ROOT, 'assets'), urls: ['/ui'], index: 'index.html'
|
30
25
|
map '/api' do
|
31
26
|
run ::AgileProxy::Api::Root.new
|
32
27
|
end
|
33
28
|
end
|
34
|
-
|
35
|
-
|
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
|
+
)
|
36
37
|
end
|
37
38
|
end
|
38
39
|
end
|
@@ -1,6 +1,4 @@
|
|
1
1
|
require 'eventmachine'
|
2
|
-
require 'goliath/api'
|
3
|
-
require 'goliath/proxy'
|
4
2
|
module AgileProxy
|
5
3
|
module Servers
|
6
4
|
#
|
@@ -8,7 +6,6 @@ module AgileProxy
|
|
8
6
|
# This server is responsible for handling or passing through a request, depending
|
9
7
|
# on if it has a matching 'Request Specification'
|
10
8
|
class RequestSpec
|
11
|
-
|
12
9
|
# Starts the server
|
13
10
|
def self.start
|
14
11
|
new.start
|
@@ -18,23 +15,16 @@ module AgileProxy
|
|
18
15
|
end
|
19
16
|
# Starts the server
|
20
17
|
def start
|
21
|
-
|
22
|
-
|
23
|
-
|
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
|
18
|
+
@signature = EM.start_server('127.0.0.1', AgileProxy.config.proxy_port, ProxyConnection) do |p|
|
19
|
+
p.handler = @request_handler
|
20
|
+
end
|
29
21
|
self
|
30
|
-
|
31
22
|
end
|
32
23
|
# The port the server is running on
|
33
24
|
# @return [Integer] The port the server is running on
|
34
25
|
def port
|
35
|
-
|
26
|
+
Socket.unpack_sockaddr_in(EM.get_sockname(@signature)).first
|
36
27
|
end
|
37
|
-
private
|
38
28
|
end
|
39
29
|
end
|
40
30
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'rack'
|
2
|
-
require '
|
3
|
-
|
2
|
+
require 'thin'
|
3
|
+
|
4
4
|
module AgileProxy
|
5
5
|
module Servers
|
6
6
|
#
|
@@ -17,17 +17,21 @@ 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
|
-
|
21
|
-
|
22
|
-
runner.address = server_host
|
23
|
-
runner.port = server_port
|
24
|
-
runner.app = ::Goliath::Rack::Builder.app do
|
20
|
+
# The sinatra web server
|
21
|
+
dispatch = Rack::Builder.app do
|
25
22
|
use Rack::Static, root: File.join(ROOT, 'assets'), urls: static_dirs, index: 'index.html' unless static_dirs.empty?
|
26
23
|
map '/' do
|
27
24
|
run ::AgileProxy::StubHandler.new
|
28
25
|
end
|
29
26
|
end
|
30
|
-
|
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
|
+
)
|
31
35
|
end
|
32
36
|
end
|
33
37
|
end
|
data/lib/agile_proxy/version.rb
CHANGED
data/spec/support/test_server.rb
CHANGED
@@ -1,80 +1,23 @@
|
|
1
|
+
require 'eventmachine'
|
2
|
+
require 'thin'
|
1
3
|
require 'faraday'
|
2
4
|
require 'agile_proxy/cli'
|
3
|
-
require 'socket'
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
def response(env)
|
12
|
-
[200, {}, "hello!"]
|
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
|
13
12
|
end
|
14
13
|
end
|
15
|
-
|
16
|
-
|
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
|
14
|
+
end
|
15
|
+
end
|
75
16
|
|
17
|
+
module AgileProxy
|
18
|
+
module TestServer
|
76
19
|
def initialize(rspecParams=nil)
|
77
|
-
|
20
|
+
Thin::Logging.silent = true
|
78
21
|
end
|
79
22
|
def proxy_port
|
80
23
|
3101
|
@@ -86,20 +29,66 @@ module AgileProxy
|
|
86
29
|
3022
|
87
30
|
end
|
88
31
|
|
89
|
-
|
90
32
|
def start_test_servers
|
91
|
-
|
92
|
-
|
93
|
-
|
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
|
+
|
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}"
|
94
55
|
end
|
95
56
|
|
96
57
|
def start_proxy_server
|
97
58
|
Thread.new do
|
98
59
|
cli = Cli.start(['start', proxy_port.to_s, server_port.to_s, api_port.to_s, '--env', 'test'])
|
99
60
|
end
|
100
|
-
sleep
|
61
|
+
sleep 1
|
101
62
|
end
|
102
63
|
|
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
|
103
80
|
|
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
|
104
93
|
end
|
105
94
|
end
|
@@ -2,16 +2,16 @@ require 'spec_helper'
|
|
2
2
|
describe AgileProxy::Servers::Api do
|
3
3
|
let(:subject) { AgileProxy::Servers::Api }
|
4
4
|
let(:rack_builder_class) { Class.new }
|
5
|
-
let(:
|
5
|
+
let(:rack_server_class) { Class.new }
|
6
6
|
let(:rack_static_class) { Class.new }
|
7
7
|
let(:api_root_class) { Class.new }
|
8
8
|
before :each do
|
9
|
-
stub_const('
|
9
|
+
stub_const('Rack::Builder', rack_builder_class)
|
10
10
|
stub_const('Rack::Static', rack_static_class)
|
11
|
-
stub_const('
|
11
|
+
stub_const('Rack::Server', rack_server_class)
|
12
12
|
stub_const('AgileProxy::Api::Root', api_root_class)
|
13
13
|
end
|
14
|
-
it 'Should start a
|
14
|
+
it 'Should start a rack server when the start method is called' do
|
15
15
|
builder_block = nil
|
16
16
|
expect(rack_builder_class).to receive(:app) do |&blk|
|
17
17
|
builder_block = blk
|
@@ -24,11 +24,7 @@ describe AgileProxy::Servers::Api do
|
|
24
24
|
rack_builder_class.new.instance_eval(&blk)
|
25
25
|
|
26
26
|
end
|
27
|
-
|
28
|
-
expect_any_instance_of(goliath_runner_class).to receive(:initialize).with([], nil)
|
29
|
-
expect_any_instance_of(goliath_runner_class).to receive(:address=).with('localhost')
|
30
|
-
expect_any_instance_of(goliath_runner_class).to receive(:port=).with('3020')
|
31
|
-
expect_any_instance_of(goliath_runner_class).to receive(:app=)
|
27
|
+
expect(rack_server_class).to receive(:start)
|
32
28
|
subject.start('localhost', '3020')
|
33
29
|
|
34
30
|
end
|
@@ -2,13 +2,13 @@ require 'spec_helper'
|
|
2
2
|
describe AgileProxy::Servers::RequestSpecDirect do
|
3
3
|
let(:subject) { AgileProxy::Servers::RequestSpecDirect }
|
4
4
|
let(:rack_builder_class) { Class.new }
|
5
|
-
let(:
|
5
|
+
let(:rack_server_class) { Class.new }
|
6
6
|
let(:rack_static_class) { Class.new }
|
7
7
|
let(:stub_handler_class) { Class.new }
|
8
8
|
before :each do
|
9
|
-
stub_const('
|
9
|
+
stub_const('Rack::Builder', rack_builder_class)
|
10
10
|
stub_const('Rack::Static', rack_static_class)
|
11
|
-
stub_const('
|
11
|
+
stub_const('Rack::Server', rack_server_class)
|
12
12
|
stub_const('AgileProxy::StubHandler', stub_handler_class)
|
13
13
|
end
|
14
14
|
it 'Should start a rack server with a static handler when the start method is called' do
|
@@ -24,11 +24,7 @@ describe AgileProxy::Servers::RequestSpecDirect do
|
|
24
24
|
rack_builder_class.new.instance_eval(&blk)
|
25
25
|
|
26
26
|
end
|
27
|
-
|
28
|
-
expect_any_instance_of(goliath_runner_class).to receive(:initialize).with([], nil)
|
29
|
-
expect_any_instance_of(goliath_runner_class).to receive(:address=).with('localhost')
|
30
|
-
expect_any_instance_of(goliath_runner_class).to receive(:port=).with('3030')
|
31
|
-
expect_any_instance_of(goliath_runner_class).to receive(:app=)
|
27
|
+
expect(rack_server_class).to receive(:start)
|
32
28
|
subject.start('localhost', '3030', ['/ui', '/images'])
|
33
29
|
|
34
30
|
end
|
@@ -44,11 +40,7 @@ describe AgileProxy::Servers::RequestSpecDirect do
|
|
44
40
|
expect_any_instance_of(rack_builder_class).to receive(:run).with(kind_of(stub_handler_class))
|
45
41
|
rack_builder_class.new.instance_eval(&blk)
|
46
42
|
end
|
47
|
-
|
48
|
-
expect_any_instance_of(goliath_runner_class).to receive(:initialize).with([], nil)
|
49
|
-
expect_any_instance_of(goliath_runner_class).to receive(:address=).with('localhost')
|
50
|
-
expect_any_instance_of(goliath_runner_class).to receive(:port=).with('3030')
|
51
|
-
expect_any_instance_of(goliath_runner_class).to receive(:app=)
|
43
|
+
expect(rack_server_class).to receive(:start)
|
52
44
|
subject.start('localhost', '3030')
|
53
45
|
|
54
46
|
end
|
@@ -1,33 +1,30 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
describe AgileProxy::Servers::RequestSpec do
|
3
3
|
let(:subject) { AgileProxy::Servers::RequestSpec }
|
4
|
-
let(:
|
5
|
-
let(:
|
6
|
-
let(:
|
4
|
+
let(:event_machine_class) { Class.new }
|
5
|
+
let(:socket_class) { Class.new }
|
6
|
+
let(:proxy_connection_class) { Class.new }
|
7
7
|
let(:request_handler_class) { Class.new }
|
8
|
-
let(:config_class) {Class.new}
|
9
8
|
before :each do
|
10
|
-
stub_const('
|
11
|
-
stub_const('
|
12
|
-
stub_const('
|
9
|
+
stub_const('EM', event_machine_class)
|
10
|
+
stub_const('Socket', socket_class)
|
11
|
+
stub_const('AgileProxy::ProxyConnection', proxy_connection_class)
|
13
12
|
stub_const('AgileProxy::RequestHandler', request_handler_class)
|
14
|
-
stub_const('AgileProxy::Config', config_class)
|
15
13
|
end
|
16
14
|
context 'With started server' do
|
17
15
|
before :each do
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
expect(AgileProxy).to receive(:config).at_least(:once).and_return config_class.new
|
24
|
-
expect_any_instance_of(config_class).to receive(:proxy_port).at_least(:once).and_return '3100'
|
25
|
-
allow_any_instance_of(config_class).to receive(:reset)
|
16
|
+
expect(event_machine_class).to receive(:start_server).with('127.0.0.1', AgileProxy.config.proxy_port, proxy_connection_class) do |_host, _port, _connection_class, &blk|
|
17
|
+
connection_instance = proxy_connection_class.new
|
18
|
+
expect(connection_instance).to receive(:handler=).with(kind_of(request_handler_class))
|
19
|
+
blk.call(connection_instance)
|
20
|
+
end.and_return 'signature'
|
26
21
|
end
|
27
22
|
it 'Should start the server and return the instance' do
|
28
23
|
expect(subject.start).to be_a_kind_of(subject)
|
29
24
|
end
|
30
25
|
it 'Should return the port it is running on' do
|
26
|
+
expect(event_machine_class).to receive(:get_sockname).with('signature').and_return 'sockname'
|
27
|
+
expect(socket_class).to receive(:unpack_sockaddr_in).with('sockname').and_return ['3100']
|
31
28
|
expect(subject.start.port).to eql '3100'
|
32
29
|
|
33
30
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: agile-proxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.22
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gary Taylor
|
@@ -124,6 +124,26 @@ dependencies:
|
|
124
124
|
- - ">="
|
125
125
|
- !ruby/object:Gem::Version
|
126
126
|
version: 2.43.0
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: rack
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - "~>"
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '1.6'
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: 1.6.0
|
137
|
+
type: :development
|
138
|
+
prerelease: false
|
139
|
+
version_requirements: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: '1.6'
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 1.6.0
|
127
147
|
- !ruby/object:Gem::Dependency
|
128
148
|
name: guard
|
129
149
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,6 +204,26 @@ dependencies:
|
|
184
204
|
- - ">="
|
185
205
|
- !ruby/object:Gem::Version
|
186
206
|
version: 1.3.17
|
207
|
+
- !ruby/object:Gem::Dependency
|
208
|
+
name: airborne
|
209
|
+
requirement: !ruby/object:Gem::Requirement
|
210
|
+
requirements:
|
211
|
+
- - "~>"
|
212
|
+
- !ruby/object:Gem::Version
|
213
|
+
version: '0.1'
|
214
|
+
- - ">="
|
215
|
+
- !ruby/object:Gem::Version
|
216
|
+
version: 0.1.10
|
217
|
+
type: :development
|
218
|
+
prerelease: false
|
219
|
+
version_requirements: !ruby/object:Gem::Requirement
|
220
|
+
requirements:
|
221
|
+
- - "~>"
|
222
|
+
- !ruby/object:Gem::Version
|
223
|
+
version: '0.1'
|
224
|
+
- - ">="
|
225
|
+
- !ruby/object:Gem::Version
|
226
|
+
version: 0.1.10
|
187
227
|
- !ruby/object:Gem::Dependency
|
188
228
|
name: rest-client
|
189
229
|
requirement: !ruby/object:Gem::Requirement
|
@@ -364,6 +404,86 @@ dependencies:
|
|
364
404
|
- - ">="
|
365
405
|
- !ruby/object:Gem::Version
|
366
406
|
version: 1.1.2
|
407
|
+
- !ruby/object:Gem::Dependency
|
408
|
+
name: eventmachine_httpserver
|
409
|
+
requirement: !ruby/object:Gem::Requirement
|
410
|
+
requirements:
|
411
|
+
- - "~>"
|
412
|
+
- !ruby/object:Gem::Version
|
413
|
+
version: '0.2'
|
414
|
+
- - ">="
|
415
|
+
- !ruby/object:Gem::Version
|
416
|
+
version: 0.2.1
|
417
|
+
type: :runtime
|
418
|
+
prerelease: false
|
419
|
+
version_requirements: !ruby/object:Gem::Requirement
|
420
|
+
requirements:
|
421
|
+
- - "~>"
|
422
|
+
- !ruby/object:Gem::Version
|
423
|
+
version: '0.2'
|
424
|
+
- - ">="
|
425
|
+
- !ruby/object:Gem::Version
|
426
|
+
version: 0.2.1
|
427
|
+
- !ruby/object:Gem::Dependency
|
428
|
+
name: http_parser.rb
|
429
|
+
requirement: !ruby/object:Gem::Requirement
|
430
|
+
requirements:
|
431
|
+
- - "~>"
|
432
|
+
- !ruby/object:Gem::Version
|
433
|
+
version: '0.6'
|
434
|
+
- - ">="
|
435
|
+
- !ruby/object:Gem::Version
|
436
|
+
version: 0.6.0
|
437
|
+
type: :runtime
|
438
|
+
prerelease: false
|
439
|
+
version_requirements: !ruby/object:Gem::Requirement
|
440
|
+
requirements:
|
441
|
+
- - "~>"
|
442
|
+
- !ruby/object:Gem::Version
|
443
|
+
version: '0.6'
|
444
|
+
- - ">="
|
445
|
+
- !ruby/object:Gem::Version
|
446
|
+
version: 0.6.0
|
447
|
+
- !ruby/object:Gem::Dependency
|
448
|
+
name: multi_json
|
449
|
+
requirement: !ruby/object:Gem::Requirement
|
450
|
+
requirements:
|
451
|
+
- - "~>"
|
452
|
+
- !ruby/object:Gem::Version
|
453
|
+
version: '1.10'
|
454
|
+
- - ">="
|
455
|
+
- !ruby/object:Gem::Version
|
456
|
+
version: 1.10.1
|
457
|
+
type: :runtime
|
458
|
+
prerelease: false
|
459
|
+
version_requirements: !ruby/object:Gem::Requirement
|
460
|
+
requirements:
|
461
|
+
- - "~>"
|
462
|
+
- !ruby/object:Gem::Version
|
463
|
+
version: '1.10'
|
464
|
+
- - ">="
|
465
|
+
- !ruby/object:Gem::Version
|
466
|
+
version: 1.10.1
|
467
|
+
- !ruby/object:Gem::Dependency
|
468
|
+
name: thin
|
469
|
+
requirement: !ruby/object:Gem::Requirement
|
470
|
+
requirements:
|
471
|
+
- - "~>"
|
472
|
+
- !ruby/object:Gem::Version
|
473
|
+
version: '1.6'
|
474
|
+
- - ">="
|
475
|
+
- !ruby/object:Gem::Version
|
476
|
+
version: 1.6.2
|
477
|
+
type: :runtime
|
478
|
+
prerelease: false
|
479
|
+
version_requirements: !ruby/object:Gem::Requirement
|
480
|
+
requirements:
|
481
|
+
- - "~>"
|
482
|
+
- !ruby/object:Gem::Version
|
483
|
+
version: '1.6'
|
484
|
+
- - ">="
|
485
|
+
- !ruby/object:Gem::Version
|
486
|
+
version: 1.6.2
|
367
487
|
- !ruby/object:Gem::Dependency
|
368
488
|
name: grape
|
369
489
|
requirement: !ruby/object:Gem::Requirement
|
@@ -499,45 +619,25 @@ dependencies:
|
|
499
619
|
- !ruby/object:Gem::Version
|
500
620
|
version: 0.19.1
|
501
621
|
- !ruby/object:Gem::Dependency
|
502
|
-
name:
|
503
|
-
requirement: !ruby/object:Gem::Requirement
|
504
|
-
requirements:
|
505
|
-
- - "~>"
|
506
|
-
- !ruby/object:Gem::Version
|
507
|
-
version: '1.0'
|
508
|
-
- - ">="
|
509
|
-
- !ruby/object:Gem::Version
|
510
|
-
version: 1.0.4
|
511
|
-
type: :runtime
|
512
|
-
prerelease: false
|
513
|
-
version_requirements: !ruby/object:Gem::Requirement
|
514
|
-
requirements:
|
515
|
-
- - "~>"
|
516
|
-
- !ruby/object:Gem::Version
|
517
|
-
version: '1.0'
|
518
|
-
- - ">="
|
519
|
-
- !ruby/object:Gem::Version
|
520
|
-
version: 1.0.4
|
521
|
-
- !ruby/object:Gem::Dependency
|
522
|
-
name: goliath-proxy
|
622
|
+
name: rack-parser
|
523
623
|
requirement: !ruby/object:Gem::Requirement
|
524
624
|
requirements:
|
525
625
|
- - "~>"
|
526
626
|
- !ruby/object:Gem::Version
|
527
|
-
version: '0.
|
627
|
+
version: '0.6'
|
528
628
|
- - ">="
|
529
629
|
- !ruby/object:Gem::Version
|
530
|
-
version: 0.
|
630
|
+
version: 0.6.1
|
531
631
|
type: :runtime
|
532
632
|
prerelease: false
|
533
633
|
version_requirements: !ruby/object:Gem::Requirement
|
534
634
|
requirements:
|
535
635
|
- - "~>"
|
536
636
|
- !ruby/object:Gem::Version
|
537
|
-
version: '0.
|
637
|
+
version: '0.6'
|
538
638
|
- - ">="
|
539
639
|
- !ruby/object:Gem::Version
|
540
|
-
version: 0.
|
640
|
+
version: 0.6.1
|
541
641
|
description: An agile, programmable, controllable proxy server for use standalone
|
542
642
|
or as part of an integration test suite with clients for many languages
|
543
643
|
email:
|
@@ -2204,7 +2304,6 @@ files:
|
|
2204
2304
|
- db/migrations/20150221152500_add_record_requests_to_request_specs.rb
|
2205
2305
|
- db/schema.rb
|
2206
2306
|
- db/seed.rb
|
2207
|
-
- echo_server.rb
|
2208
2307
|
- examples/README.md
|
2209
2308
|
- examples/facebook_api.html
|
2210
2309
|
- examples/tumblr_api.html
|
data/echo_server.rb
DELETED
@@ -1,19 +0,0 @@
|
|
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
|