agile-proxy 0.1.22 → 0.1.23
Sign up to get free protection for your applications and to get access to all the features.
- 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
|