agile-proxy 0.1.22 → 0.1.23
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 +2 -1
- data/README.md +1 -0
- data/agile-proxy.gemspec +14 -8
- data/echo_server.rb +19 -0
- data/lib/agile_proxy/handlers/request_handler.rb +2 -1
- data/lib/agile_proxy/handlers/stub_handler.rb +1 -1
- data/lib/agile_proxy/model/recording.rb +1 -0
- data/lib/agile_proxy/model/response.rb +1 -1
- data/lib/agile_proxy/proxy_connection.rb +27 -28
- data/lib/agile_proxy/server.rb +15 -1
- data/lib/agile_proxy/servers/api.rb +10 -11
- data/lib/agile_proxy/servers/request_spec.rb +14 -4
- data/lib/agile_proxy/servers/request_spec_direct.rb +8 -12
- data/lib/agile_proxy/version.rb +1 -1
- data/spec/integration/specs/lib/server_spec.rb +19 -12
- data/spec/integration_spec_helper.rb +1 -0
- data/spec/support/test_server.rb +75 -64
- data/spec/unit/agile_proxy/handlers/stub_handler_spec.rb +28 -16
- data/spec/unit/agile_proxy/model/response_spec.rb +3 -3
- data/spec/unit/agile_proxy/servers/api_spec.rb +9 -5
- data/spec/unit/agile_proxy/servers/request_spec_direct_spec.rb +13 -5
- data/spec/unit/agile_proxy/servers/request_spec_spec.rb +16 -13
- metadata +29 -128
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3bbb90ecd388cd7e950d4a7fe7bf6b2c22a81218
|
4
|
+
data.tar.gz: 0d9631df2bce4c44899f1a87e1479eee8ccf5e4a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 91e4deda16860bbe0efa661180a0c4dd0926a59b34ef30686fe91bd72f9b87d1fd9ee3d88f693b93651c8252fd713edfc2b01555f93e49bfac0ffc59b7c25128
|
7
|
+
data.tar.gz: 87955fdff1298490172056333ddc0dfe8a9f17f50dc77c9db3af60e160e7bae7420bc0d2dcba3226a1cc0d67799d978f1e6071a932b09bf86caa721f2a9ab7b8
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -124,4 +124,5 @@ v0.1.19 - Recordings now record the request spec id.
|
|
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
126
|
v0.1.22 - Reverted 0.1.21 - Integration tests worked fine, but failed in real world scenario - never ending responses from stubs
|
127
|
+
v0.1.23 - Switched to goliath instead of thin. The gem now installs under jruby as well as other platforms.
|
127
128
|
|
data/agile-proxy.gemspec
CHANGED
@@ -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
|
-
|
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 '
|
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
|
data/echo_server.rb
ADDED
@@ -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
|
@@ -101,6 +100,7 @@ module AgileProxy
|
|
101
100
|
Rack::Builder.new do
|
102
101
|
use ActionDispatch::ParamsParser, Mime::TEXT => text_handler
|
103
102
|
use MergePostAndGetParams
|
103
|
+
use Rack::ContentLength
|
104
104
|
run route_set
|
105
105
|
end
|
106
106
|
end
|
@@ -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 <
|
16
|
-
|
13
|
+
class ProxyConnection < Goliath::Connection
|
14
|
+
def logger
|
15
|
+
::AgileProxy.config.logger
|
16
|
+
end
|
17
17
|
def post_init
|
18
|
-
|
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 @
|
40
|
-
restart_with_ssl(@
|
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(@
|
46
|
+
uri = URI.parse(@proxy_parser.request_url)
|
44
47
|
@url = "https://#{@ssl}#{[uri.path, uri.query].compact.join('?')}"
|
45
48
|
else
|
46
|
-
@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
|
-
@
|
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 =
|
68
|
-
request.
|
69
|
-
|
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' => @
|
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
|
-
|
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
|
data/lib/agile_proxy/server.rb
CHANGED
@@ -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
|
-
#
|
23
|
-
|
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
|
-
|
30
|
-
|
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
|
-
|
19
|
-
|
20
|
-
|
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
|
-
|
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 '
|
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
|
-
|
21
|
-
|
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
|
-
|
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
|
data/lib/agile_proxy/version.rb
CHANGED
@@ -56,13 +56,17 @@ shared_examples_for 'a request stub' do |options = {}|
|
|
56
56
|
stub = find_stub(http, name)
|
57
57
|
{recordings: a_collection_containing_exactly(a_hash_including request_body: '', request_url: "#{http.url_prefix}#{path.gsub(/^\//, '')}", request_method: 'GET', request_spec_id: stub.body[:id])}
|
58
58
|
end
|
59
|
+
|
59
60
|
it 'should stub GET requests' do
|
60
|
-
|
61
|
+
response = http.get('/index.html')
|
62
|
+
expect(response.body).to eql '<html><body>Mocked Content</body></html>'
|
63
|
+
expect(response.headers).to include('content-length' => "40")
|
61
64
|
expect(recordings_for 'index').to include(recordings_matcher_for('index', '/index.html')) if recording
|
62
65
|
end
|
63
66
|
|
64
67
|
it 'should stub GET response statuses' do
|
65
|
-
|
68
|
+
response = http.get('/index.html')
|
69
|
+
expect(response.status).to eql 200
|
66
70
|
end
|
67
71
|
|
68
72
|
#TODO When time allows, work out how to easily test this as the stubs are not recorded for anything but recorded tests
|
@@ -77,7 +81,7 @@ shared_examples_for 'a request stub' do |options = {}|
|
|
77
81
|
resp = http.get('/api/forums')
|
78
82
|
expect(ActiveSupport::JSON.decode(resp.body).symbolize_keys).to eql forums: [], total: 0
|
79
83
|
expect(resp.status).to eql 200
|
80
|
-
expect(resp.headers
|
84
|
+
expect(resp.headers).to include('content-type' => 'application/json', 'content-length' => resp.body.length.to_s)
|
81
85
|
expect(recordings_for 'api_forums').to include(recordings_matcher_for('api_forums', '/api/forums')) if recording
|
82
86
|
end
|
83
87
|
|
@@ -85,43 +89,44 @@ shared_examples_for 'a request stub' do |options = {}|
|
|
85
89
|
resp = http.get '/api/forums/my_forum/posts'
|
86
90
|
expect(ActiveSupport::JSON.decode(resp.body)).to eql 'posts' => [{ 'forum_id' => 'my_forum', 'subject' => 'My first post' }, { 'forum_id' => 'my_forum', 'subject' => 'My second post' }, { 'forum_id' => 'my_forum', 'subject' => 'My third post' }], 'total' => 3
|
87
91
|
expect(resp.status).to eql 200
|
88
|
-
expect(resp.headers
|
92
|
+
expect(resp.headers).to include('content-type' => 'application/json', 'content-length' => resp.body.length.to_s)
|
89
93
|
end
|
90
94
|
|
91
95
|
it 'Should get the mocked content for api/forums/:forum_id/:post_id with parameter substitution including query parameters' do
|
92
96
|
resp = http.get '/api/forums/my_forum/my_post?sort=id'
|
93
97
|
expect(resp.body).to eql '<html><body><h1>Sorted By: id</h1><h2>my_forum</h2><h3>my_post</h3></body></html>'
|
94
98
|
expect(resp.status).to eql 200
|
95
|
-
expect(resp.headers
|
99
|
+
expect(resp.headers).to include('content-type' => 'text/html', 'content-length' => resp.body.length.to_s)
|
96
100
|
end
|
97
101
|
it 'Should get the mocked content for api/forums/:forum_id/:post_id.html with parameter substitution including query parameters' do
|
98
102
|
resp = http.get '/api/forums/my_forum/my_post.html?sort=id'
|
99
103
|
expect(resp.body).to eql '<html><body><h1>Sorted By: id</h1><h2>my_forum</h2><h3>my_post</h3></body></html>'
|
100
104
|
expect(resp.status).to eql 200
|
101
|
-
expect(resp.headers
|
105
|
+
expect(resp.headers).to include('content-type' => 'text/html', 'content-length' => resp.body.length.to_s)
|
102
106
|
end
|
103
107
|
it 'Should respond with an error for api/forums/:forum_id/:post_id.html with parameter substitution with a missing query parameter' do
|
104
108
|
resp = http.get '/api/forums/my_forum/my_post.html'
|
105
109
|
expect(resp.body).to eql '<html><body><h1>Sorted By: </h1><h2>my_forum</h2><h3>my_post</h3></body></html>'
|
110
|
+
expect(resp.headers).to include('content-type' => 'text/html', 'content-length' => resp.body.length.to_s)
|
106
111
|
expect(resp.status).to eql 200
|
107
112
|
end
|
108
113
|
it 'Should match the route by posted json data and the posted data can be output via the template' do
|
109
114
|
resp = http.post '/api/forums/my_forum', '{"posted_var": "special_value"}', 'Content-Type' => 'application/json'
|
110
115
|
expect(resp.body).to eql '<html><body><h1></h1><h2>special_value</h2><h3>my_forum</h3><p>This should get data from the POSTed data</p></body></html>'
|
111
116
|
expect(resp.status).to eql 200
|
112
|
-
expect(resp.headers
|
117
|
+
expect(resp.headers).to include('content-type' => 'text/html', 'content-length' => resp.body.length.to_s)
|
113
118
|
end
|
114
119
|
it 'Should match the route by posted plain text data and the posted data can be output via the template' do
|
115
120
|
resp = http.post '/api/forums/my_forum', "posted_var=special_value\n", 'Content-Type' => 'text/plain'
|
116
121
|
expect(resp.body).to eql '<html><body><h1></h1><h2>special_value</h2><h3>my_forum</h3><p>This should get data from the POSTed data</p></body></html>'
|
117
122
|
expect(resp.status).to eql 200
|
118
|
-
expect(resp.headers
|
123
|
+
expect(resp.headers).to include('content-type' => 'text/html', 'content-length' => resp.body.length.to_s)
|
119
124
|
end
|
120
125
|
it 'Should match the route by posted plain text data and the posted data can be output via the template' do
|
121
126
|
resp = http.post '/api/forums/my_forum', "dummy=\nposted_var=special_value\n", 'Content-Type' => 'text/plain'
|
122
127
|
expect(resp.body).to eql '<html><body><h1></h1><h2>special_value</h2><h3>my_forum</h3><p>This should get data from the POSTed data</p></body></html>'
|
123
128
|
expect(resp.status).to eql 200
|
124
|
-
expect(resp.headers
|
129
|
+
expect(resp.headers).to include('content-type' => 'text/html', 'content-length' => resp.body.length.to_s)
|
125
130
|
end
|
126
131
|
# it 'Should match the route by posted xml data and the posted data can be output via the template' do
|
127
132
|
# resp = http.post "/api/forums/my_forum", '<posted_var>special_value</posted_var>', {'Content-Type' => 'application/xml'}
|
@@ -131,31 +136,33 @@ shared_examples_for 'a request stub' do |options = {}|
|
|
131
136
|
it 'Should match the route by posted url encoded data and the posted data can be output via the template' do
|
132
137
|
resp = http.post '/api/forums/my_forum', 'posted_var=special_value', 'Content-Type' => 'application/x-www-form-urlencoded'
|
133
138
|
expect(resp.body).to eql '<html><body><h1></h1><h2>special_value</h2><h3>my_forum</h3><p>This should get data from the POSTed data</p></body></html>'
|
139
|
+
expect(resp.headers).to include('content-type' => 'text/html', 'content-length' => resp.body.length.to_s)
|
134
140
|
expect(resp.status).to eql 200
|
135
141
|
end
|
136
142
|
it 'Should match the route by posted multipart encoded data and the posted data can be output via the template' do
|
137
143
|
resp = http.post '/api/forums/my_forum', 'posted_var=special_value', 'Content-Type' => 'multipart/form-data'
|
138
144
|
expect(resp.body).to eql '<html><body><h1></h1><h2>special_value</h2><h3>my_forum</h3><p>This should get data from the POSTed data</p></body></html>'
|
145
|
+
expect(resp.headers).to include('content-type' => 'text/html', 'content-length' => resp.body.length.to_s)
|
139
146
|
expect(resp.status).to eql 200
|
140
147
|
end
|
141
148
|
|
142
149
|
it 'should stub POST requests' do
|
143
150
|
resp = http.post('/api/forums', foo: :bar)
|
144
151
|
expect(resp.body).to eql '{"created": true}'
|
145
|
-
expect(resp.headers
|
152
|
+
expect(resp.headers).to include('content-type' => 'application/json', 'content-length' => resp.body.length.to_s)
|
146
153
|
|
147
154
|
end
|
148
155
|
|
149
156
|
it 'should stub PUT requests' do
|
150
157
|
resp = http.put('/api/forums/forum_1/my_post', foo: :bar)
|
151
158
|
expect(resp.body).to eql '{"updated": true}'
|
152
|
-
expect(resp.headers
|
159
|
+
expect(resp.headers).to include('content-type' => 'application/json', 'content-length' => resp.body.length.to_s)
|
153
160
|
end
|
154
161
|
|
155
162
|
it 'should stub DELETE requests' do
|
156
163
|
resp = http.delete('/api/forums/forum_1/my_post')
|
157
164
|
expect(resp.body).to eql '{"deleted": true}'
|
158
|
-
expect(resp.headers
|
165
|
+
expect(resp.headers).to include('content-type' => 'application/json', 'content-length' => resp.body.length.to_s)
|
159
166
|
end
|
160
167
|
end
|
161
168
|
|
data/spec/support/test_server.rb
CHANGED
@@ -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
|
-
|
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
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
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
|
@@ -1,6 +1,17 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe AgileProxy::StubHandler do
|
4
|
+
#Mock the content length middleware as we are not testing if that works
|
5
|
+
let(:rack_content_length_class) do
|
6
|
+
Class.new do
|
7
|
+
def initialize(app)
|
8
|
+
@app = app
|
9
|
+
end
|
10
|
+
def call(env)
|
11
|
+
@app.call(env)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
4
15
|
let(:route_not_found_response) { [404, { 'X-Cascade' => 'pass' }, ['Not Found']] }
|
5
16
|
let(:handler) { AgileProxy::StubHandler.new }
|
6
17
|
let(:request) do
|
@@ -23,6 +34,7 @@ describe AgileProxy::StubHandler do
|
|
23
34
|
|
24
35
|
before :each do
|
25
36
|
stub_const('AgileProxy::Application', application_class)
|
37
|
+
stub_const('Rack::ContentLength', rack_content_length_class)
|
26
38
|
allow(application_class).to receive(:where).and_return application_class
|
27
39
|
allow(application_class).to receive(:first).and_return application
|
28
40
|
allow(application).to receive(:request_specs).and_return request_spec_class
|
@@ -71,8 +83,8 @@ describe AgileProxy::StubHandler do
|
|
71
83
|
it 'Should match with a get on the same domain but not with a post or a different domain' do
|
72
84
|
expect(handler.call(request_for(url: 'http://example.com').env)).to eql([200, {}, ''])
|
73
85
|
expect(handler.call(request_for(url: 'http://example.com/').env)).to eql([200, {}, ''])
|
74
|
-
expect(handler.call(request_for(url: 'http://example.com/', method: 'POST').env)).to
|
75
|
-
expect(handler.call(request_for(url: 'http://subdomain.example.com/').env)).to
|
86
|
+
expect(handler.call(request_for(url: 'http://example.com/', method: 'POST').env)).to contain_exactly *route_not_found_response
|
87
|
+
expect(handler.call(request_for(url: 'http://subdomain.example.com/').env)).to contain_exactly *route_not_found_response
|
76
88
|
end
|
77
89
|
|
78
90
|
end
|
@@ -85,10 +97,10 @@ describe AgileProxy::StubHandler do
|
|
85
97
|
end
|
86
98
|
it 'Should match with a get on the same domain but not with a post or a different domain' do
|
87
99
|
expect(handler.call(request_for(url: 'http://example.com/index').env)).to eql([200, {}, ''])
|
88
|
-
expect(handler.call(request_for(method: 'POST', url: 'http://example.com/index').env)).to
|
89
|
-
expect(handler.call(request_for(url: 'http://subdomain.example.com/index').env)).to
|
90
|
-
expect(handler.call(request_for(url: 'http://example.com/').env)).to
|
91
|
-
expect(handler.call(request_for(url: 'http://example.com').env)).to
|
100
|
+
expect(handler.call(request_for(method: 'POST', url: 'http://example.com/index').env)).to contain_exactly *route_not_found_response
|
101
|
+
expect(handler.call(request_for(url: 'http://subdomain.example.com/index').env)).to contain_exactly *route_not_found_response
|
102
|
+
expect(handler.call(request_for(url: 'http://example.com/').env)).to contain_exactly *route_not_found_response
|
103
|
+
expect(handler.call(request_for(url: 'http://example.com').env)).to contain_exactly *route_not_found_response
|
92
104
|
end
|
93
105
|
|
94
106
|
end
|
@@ -103,8 +115,8 @@ describe AgileProxy::StubHandler do
|
|
103
115
|
expect(handler.call(request_for(method: 'POST', url: 'http://example.com').env)).to eql([200, {}, ''])
|
104
116
|
expect(handler.call(request_for(method: 'POST', url: 'http://example.com/').env)).to eql([200, {}, ''])
|
105
117
|
expect(handler.call(request_for(method: 'POST', url: 'http://example.com/', headers: {'Content-Type' => 'text/plain'}, body: "a=1\nb=2\nc=3").env)).to eql([200, {}, ''])
|
106
|
-
expect(handler.call(request_for(url: 'http://example.com/').env)).to
|
107
|
-
expect(handler.call(request_for(method: 'POST', url: 'http://subdomain.example.com/').env)).to
|
118
|
+
expect(handler.call(request_for(url: 'http://example.com/').env)).to contain_exactly *route_not_found_response
|
119
|
+
expect(handler.call(request_for(method: 'POST', url: 'http://subdomain.example.com/').env)).to contain_exactly *route_not_found_response
|
108
120
|
end
|
109
121
|
|
110
122
|
end
|
@@ -116,10 +128,10 @@ describe AgileProxy::StubHandler do
|
|
116
128
|
end
|
117
129
|
it 'Should match with a get on the same domain but not with a post or a different domain' do
|
118
130
|
expect(handler.call(request_for(url: 'http://example.com/users/1/index').env)).to eql([200, {}, ''])
|
119
|
-
expect(handler.call(request_for(url: 'http://example.com/users/2/index').env)).to
|
120
|
-
expect(handler.call(request_for(method: 'POST', url: 'http://example.com/users/1/index').env)).to
|
121
|
-
expect(handler.call(request_for(url: 'http://example.com/users/1/').env)).to
|
122
|
-
expect(handler.call(request_for(url: 'http://example.com/users/1').env)).to
|
131
|
+
expect(handler.call(request_for(url: 'http://example.com/users/2/index').env)).to contain_exactly *route_not_found_response
|
132
|
+
expect(handler.call(request_for(method: 'POST', url: 'http://example.com/users/1/index').env)).to contain_exactly *route_not_found_response
|
133
|
+
expect(handler.call(request_for(url: 'http://example.com/users/1/').env)).to contain_exactly *route_not_found_response
|
134
|
+
expect(handler.call(request_for(url: 'http://example.com/users/1').env)).to contain_exactly *route_not_found_response
|
123
135
|
end
|
124
136
|
end
|
125
137
|
describe 'With a more complex route with conditions including query params inside a domain' do
|
@@ -131,10 +143,10 @@ describe AgileProxy::StubHandler do
|
|
131
143
|
it 'Should match with a get on the same domain but not with a post or a different domain' do
|
132
144
|
expect(handler.call(request_for(url: 'http://example.com/users/1/index?extra_1=extra_1&extra_2=extra_2').env)).to eql([200, {}, ''])
|
133
145
|
expect(handler.call(request_for(url: 'http://example.com/users/1/index?some_other=2&extra_1=extra_1&extra_2=extra_2').env)).to eql([200, {}, ''])
|
134
|
-
expect(handler.call(request_for(url: 'http://example.com/users/2/index').env)).to
|
135
|
-
expect(handler.call(request_for(method: 'POST', url: 'http://example.com/users/1/index').env)).to
|
136
|
-
expect(handler.call(request_for(url: 'http://example.com/users/1/').env)).to
|
137
|
-
expect(handler.call(request_for(url: 'http://example.com/users/1').env)).to
|
146
|
+
expect(handler.call(request_for(url: 'http://example.com/users/2/index').env)).to contain_exactly *route_not_found_response
|
147
|
+
expect(handler.call(request_for(method: 'POST', url: 'http://example.com/users/1/index').env)).to contain_exactly *route_not_found_response
|
148
|
+
expect(handler.call(request_for(url: 'http://example.com/users/1/').env)).to contain_exactly *route_not_found_response
|
149
|
+
expect(handler.call(request_for(url: 'http://example.com/users/1').env)).to contain_exactly *route_not_found_response
|
138
150
|
end
|
139
151
|
end
|
140
152
|
|
@@ -15,7 +15,7 @@ describe AgileProxy::Response do
|
|
15
15
|
end
|
16
16
|
it 'Should respond with a delay using the Em::Synchrony.sleep method' do
|
17
17
|
expect(EventMachine::Synchrony).to receive(:sleep).with(0.5)
|
18
|
-
expect(subject.to_rack({}, {}, '')).to eql([200, { 'Content-Type' => 'text/plain' }, 'Test'])
|
18
|
+
expect(subject.to_rack({}, {}, '')).to eql([200, { 'Content-Type' => 'text/plain' }, ['Test']])
|
19
19
|
end
|
20
20
|
|
21
21
|
end
|
@@ -27,10 +27,10 @@ describe AgileProxy::Response do
|
|
27
27
|
subject.content_type = 'text/plain'
|
28
28
|
end
|
29
29
|
it 'Should pass the params to the template and the output should be correct' do
|
30
|
-
expect(subject.to_rack({ name: 'World' }, {}, '')).to eql([200, { 'Content-Type' => 'text/plain' }, 'Hello World'])
|
30
|
+
expect(subject.to_rack({ name: 'World' }, {}, '')).to eql([200, { 'Content-Type' => 'text/plain' }, ['Hello World']])
|
31
31
|
end
|
32
32
|
it 'Should deal with if a parameter is missing' do
|
33
|
-
expect(subject.to_rack({}, {}, '')).to eql([200, { 'Content-Type' => 'text/plain' }, "Hello "])
|
33
|
+
expect(subject.to_rack({}, {}, '')).to eql([200, { 'Content-Type' => 'text/plain' }, ["Hello "]])
|
34
34
|
end
|
35
35
|
end
|
36
36
|
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(:goliath_runner_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('Rack::Builder', rack_builder_class)
|
9
|
+
stub_const('Goliath::Rack::Builder', rack_builder_class)
|
10
10
|
stub_const('Rack::Static', rack_static_class)
|
11
|
-
stub_const('
|
11
|
+
stub_const('Goliath::Runner', goliath_runner_class)
|
12
12
|
stub_const('AgileProxy::Api::Root', api_root_class)
|
13
13
|
end
|
14
|
-
it 'Should start a
|
14
|
+
it 'Should start a goliath 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,7 +24,11 @@ describe AgileProxy::Servers::Api do
|
|
24
24
|
rack_builder_class.new.instance_eval(&blk)
|
25
25
|
|
26
26
|
end
|
27
|
-
|
27
|
+
expect_any_instance_of(goliath_runner_class).to receive(:run)
|
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=)
|
28
32
|
subject.start('localhost', '3020')
|
29
33
|
|
30
34
|
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(:goliath_runner_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('Rack::Builder', rack_builder_class)
|
9
|
+
stub_const('Goliath::Rack::Builder', rack_builder_class)
|
10
10
|
stub_const('Rack::Static', rack_static_class)
|
11
|
-
stub_const('
|
11
|
+
stub_const('Goliath::Runner', goliath_runner_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,7 +24,11 @@ describe AgileProxy::Servers::RequestSpecDirect do
|
|
24
24
|
rack_builder_class.new.instance_eval(&blk)
|
25
25
|
|
26
26
|
end
|
27
|
-
|
27
|
+
expect_any_instance_of(goliath_runner_class).to receive(:run)
|
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=)
|
28
32
|
subject.start('localhost', '3030', ['/ui', '/images'])
|
29
33
|
|
30
34
|
end
|
@@ -40,7 +44,11 @@ describe AgileProxy::Servers::RequestSpecDirect do
|
|
40
44
|
expect_any_instance_of(rack_builder_class).to receive(:run).with(kind_of(stub_handler_class))
|
41
45
|
rack_builder_class.new.instance_eval(&blk)
|
42
46
|
end
|
43
|
-
|
47
|
+
expect_any_instance_of(goliath_runner_class).to receive(:run)
|
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=)
|
44
52
|
subject.start('localhost', '3030')
|
45
53
|
|
46
54
|
end
|
@@ -1,30 +1,33 @@
|
|
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(:rack_builder_class) { Class.new }
|
5
|
+
let(:goliath_runner_class) { Class.new }
|
6
|
+
let(:rack_static_class) { Class.new }
|
7
7
|
let(:request_handler_class) { Class.new }
|
8
|
+
let(:config_class) {Class.new}
|
8
9
|
before :each do
|
9
|
-
stub_const('
|
10
|
-
stub_const('
|
11
|
-
stub_const('
|
10
|
+
stub_const('Goliath::Rack::Builder', rack_builder_class)
|
11
|
+
stub_const('Rack::Static', rack_static_class)
|
12
|
+
stub_const('Goliath::Proxy::Runner', goliath_runner_class)
|
12
13
|
stub_const('AgileProxy::RequestHandler', request_handler_class)
|
14
|
+
stub_const('AgileProxy::Config', config_class)
|
13
15
|
end
|
14
16
|
context 'With started server' do
|
15
17
|
before :each do
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
18
|
+
expect_any_instance_of(goliath_runner_class).to receive(:run)
|
19
|
+
expect_any_instance_of(goliath_runner_class).to receive(:initialize).with([], nil)
|
20
|
+
expect_any_instance_of(goliath_runner_class).to receive(:address=).with('127.0.0.1')
|
21
|
+
expect_any_instance_of(goliath_runner_class).to receive(:port=).with('3100')
|
22
|
+
expect_any_instance_of(goliath_runner_class).to receive(:app=).with(instance_of(request_handler_class))
|
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)
|
21
26
|
end
|
22
27
|
it 'Should start the server and return the instance' do
|
23
28
|
expect(subject.start).to be_a_kind_of(subject)
|
24
29
|
end
|
25
30
|
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']
|
28
31
|
expect(subject.start.port).to eql '3100'
|
29
32
|
|
30
33
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
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.23
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gary Taylor
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-03-
|
11
|
+
date: 2015-03-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -124,26 +124,6 @@ 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
|
147
127
|
- !ruby/object:Gem::Dependency
|
148
128
|
name: guard
|
149
129
|
requirement: !ruby/object:Gem::Requirement
|
@@ -204,26 +184,6 @@ dependencies:
|
|
204
184
|
- - ">="
|
205
185
|
- !ruby/object:Gem::Version
|
206
186
|
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
|
227
187
|
- !ruby/object:Gem::Dependency
|
228
188
|
name: rest-client
|
229
189
|
requirement: !ruby/object:Gem::Requirement
|
@@ -404,86 +364,6 @@ dependencies:
|
|
404
364
|
- - ">="
|
405
365
|
- !ruby/object:Gem::Version
|
406
366
|
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
|
487
367
|
- !ruby/object:Gem::Dependency
|
488
368
|
name: grape
|
489
369
|
requirement: !ruby/object:Gem::Requirement
|
@@ -619,25 +499,45 @@ dependencies:
|
|
619
499
|
- !ruby/object:Gem::Version
|
620
500
|
version: 0.19.1
|
621
501
|
- !ruby/object:Gem::Dependency
|
622
|
-
name:
|
502
|
+
name: goliath
|
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
|
623
523
|
requirement: !ruby/object:Gem::Requirement
|
624
524
|
requirements:
|
625
525
|
- - "~>"
|
626
526
|
- !ruby/object:Gem::Version
|
627
|
-
version: '0.
|
527
|
+
version: '0.0'
|
628
528
|
- - ">="
|
629
529
|
- !ruby/object:Gem::Version
|
630
|
-
version: 0.
|
530
|
+
version: 0.0.1
|
631
531
|
type: :runtime
|
632
532
|
prerelease: false
|
633
533
|
version_requirements: !ruby/object:Gem::Requirement
|
634
534
|
requirements:
|
635
535
|
- - "~>"
|
636
536
|
- !ruby/object:Gem::Version
|
637
|
-
version: '0.
|
537
|
+
version: '0.0'
|
638
538
|
- - ">="
|
639
539
|
- !ruby/object:Gem::Version
|
640
|
-
version: 0.
|
540
|
+
version: 0.0.1
|
641
541
|
description: An agile, programmable, controllable proxy server for use standalone
|
642
542
|
or as part of an integration test suite with clients for many languages
|
643
543
|
email:
|
@@ -2304,6 +2204,7 @@ files:
|
|
2304
2204
|
- db/migrations/20150221152500_add_record_requests_to_request_specs.rb
|
2305
2205
|
- db/schema.rb
|
2306
2206
|
- db/seed.rb
|
2207
|
+
- echo_server.rb
|
2307
2208
|
- examples/README.md
|
2308
2209
|
- examples/facebook_api.html
|
2309
2210
|
- examples/tumblr_api.html
|
@@ -2379,7 +2280,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
2379
2280
|
version: '0'
|
2380
2281
|
requirements: []
|
2381
2282
|
rubyforge_project:
|
2382
|
-
rubygems_version: 2.
|
2283
|
+
rubygems_version: 2.4.3
|
2383
2284
|
signing_key:
|
2384
2285
|
specification_version: 4
|
2385
2286
|
summary: An agile, programmable, controllable flexible proxy server for development
|