sitehub 0.4.2 → 0.4.3
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/.rubocop.yml +17 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +15 -1
- data/README.md +23 -0
- data/Rakefile +3 -9
- data/circle.yml +6 -0
- data/lib/sitehub/builder.rb +19 -19
- data/lib/sitehub/collection/route_collection.rb +7 -9
- data/lib/sitehub/collection/split_route_collection/split.rb +7 -5
- data/lib/sitehub/collection/split_route_collection.rb +13 -10
- data/lib/sitehub/collection.rb +26 -21
- data/lib/sitehub/constants/http_header_keys.rb +2 -6
- data/lib/sitehub/constants/rack_http_header_keys.rb +2 -2
- data/lib/sitehub/constants.rb +3 -3
- data/lib/sitehub/cookie/attribute.rb +4 -4
- data/lib/sitehub/cookie/flag.rb +4 -5
- data/lib/sitehub/cookie.rb +10 -14
- data/lib/sitehub/cookie_rewriting.rb +11 -13
- data/lib/sitehub/forward_proxies.rb +12 -13
- data/lib/sitehub/forward_proxy.rb +38 -24
- data/lib/sitehub/forward_proxy_builder.rb +38 -21
- data/lib/sitehub/http_headers.rb +39 -26
- data/lib/sitehub/logging/access_logger.rb +39 -35
- data/lib/sitehub/logging/error_logger.rb +7 -7
- data/lib/sitehub/logging/log_entry.rb +6 -5
- data/lib/sitehub/logging/log_stash.rb +2 -2
- data/lib/sitehub/logging/log_wrapper.rb +5 -5
- data/lib/sitehub/logging.rb +1 -1
- data/lib/sitehub/middleware.rb +2 -2
- data/lib/sitehub/path_directive.rb +10 -10
- data/lib/sitehub/path_directives.rb +5 -4
- data/lib/sitehub/request_mapping.rb +13 -11
- data/lib/sitehub/resolver.rb +5 -6
- data/lib/sitehub/reverse_proxy.rb +16 -12
- data/lib/sitehub/rules.rb +2 -2
- data/lib/sitehub/string_sanitiser.rb +1 -1
- data/lib/sitehub/transaction_id.rb +3 -3
- data/lib/sitehub/version.rb +1 -1
- data/lib/sitehub.rb +1 -1
- data/sitehub.gemspec +27 -29
- data/spec/sitehub/builder_spec.rb +18 -20
- data/spec/sitehub/collection/route_collection_spec.rb +16 -14
- data/spec/sitehub/collection/split_route_collection_spec.rb +8 -10
- data/spec/sitehub/collection_spec.rb +7 -7
- data/spec/sitehub/cookie/attribute_spec.rb +3 -3
- data/spec/sitehub/cookie/flag_spec.rb +2 -2
- data/spec/sitehub/cookie_rewriting_spec.rb +15 -12
- data/spec/sitehub/cookie_spec.rb +7 -18
- data/spec/sitehub/error_handling_spec.rb +2 -3
- data/spec/sitehub/forward_proxies_spec.rb +16 -12
- data/spec/sitehub/forward_proxy_builder_spec.rb +53 -30
- data/spec/sitehub/forward_proxy_spec.rb +26 -22
- data/spec/sitehub/http_headers_spec.rb +17 -18
- data/spec/sitehub/integration_spec.rb +4 -5
- data/spec/sitehub/logging/access_logger_spec.rb +25 -24
- data/spec/sitehub/logging/error_logger_spec.rb +5 -7
- data/spec/sitehub/logging/log_entry_spec.rb +2 -5
- data/spec/sitehub/logging/log_stash_spec.rb +1 -3
- data/spec/sitehub/logging/log_wrapper_spec.rb +0 -4
- data/spec/sitehub/middleware_spec.rb +1 -5
- data/spec/sitehub/path_directive_spec.rb +4 -7
- data/spec/sitehub/path_directives_spec.rb +6 -7
- data/spec/sitehub/request_mapping_spec.rb +2 -5
- data/spec/sitehub/resolver_spec.rb +1 -1
- data/spec/sitehub/reverse_proxy_spec.rb +37 -31
- data/spec/sitehub/transaction_id_spec.rb +3 -3
- data/spec/sitehub_spec.rb +2 -4
- data/spec/support/async/callback.rb +11 -0
- data/spec/support/async/middleware.rb +25 -0
- data/spec/support/async/response_handler.rb +16 -0
- data/spec/support/async.rb +4 -0
- data/spec/support/patch/rack/response.rb +13 -21
- data/spec/support/shared_contexts/async_context.rb +3 -58
- data/spec/support/shared_contexts/middleware_context.rb +15 -17
- data/spec/support/shared_contexts/rack_test_context.rb +3 -3
- data/spec/support/shared_contexts/sitehub_context.rb +9 -4
- data/spec/support/silent_warnings.rb +2 -3
- data/tasks/code_quality.rake +15 -0
- data/tasks/gem_tasks.rake +1 -0
- data/tasks/support/console.rb +7 -0
- data/tasks/testing.rake +4 -0
- data/tasks/util_tasks.rake +7 -0
- metadata +27 -3
- data/spec/basket_spec.rb +0 -30
@@ -3,8 +3,7 @@ require 'sitehub/logging/error_logger'
|
|
3
3
|
class SiteHub
|
4
4
|
module Logging
|
5
5
|
describe ErrorLogger do
|
6
|
-
|
7
|
-
let(:app){ proc{[200, {}, []]}}
|
6
|
+
let(:app) { proc { [200, {}, []] } }
|
8
7
|
subject { described_class.new(app) }
|
9
8
|
|
10
9
|
describe '#initialize' do
|
@@ -44,7 +43,7 @@ class SiteHub
|
|
44
43
|
context 'errors have occurred' do
|
45
44
|
it 'logs errors' do
|
46
45
|
log_message = subject.log_message(error: error_message, transaction_id: :transaction_id)
|
47
|
-
subject.call(
|
46
|
+
subject.call(ERRORS => errors, Constants::RackHttpHeaderKeys::TRANSACTION_ID => :transaction_id)
|
48
47
|
expect(output.string).to eq(log_message)
|
49
48
|
end
|
50
49
|
end
|
@@ -52,7 +51,7 @@ class SiteHub
|
|
52
51
|
context 'no errors have occured' do
|
53
52
|
it 'does not log anything' do
|
54
53
|
expect(logger).to_not receive(:write)
|
55
|
-
subject.call(
|
54
|
+
subject.call(ERRORS => [])
|
56
55
|
end
|
57
56
|
end
|
58
57
|
end
|
@@ -62,17 +61,16 @@ class SiteHub
|
|
62
61
|
it 'contains the time and date' do
|
63
62
|
now = Time.now
|
64
63
|
expect(Time).to receive(:now).and_return(now)
|
65
|
-
expected_time = now.strftime(
|
64
|
+
expected_time = now.strftime('%d/%b/%Y:%H:%M:%S %z')
|
66
65
|
expect(subject.log_message(error: error, transaction_id: :transaction_id)).to start_with("[#{expected_time}]")
|
67
66
|
end
|
68
67
|
|
69
68
|
it 'logs statements made against blah' do
|
70
|
-
|
71
69
|
expect(subject.log_message(error: error, transaction_id: :transaction_id)).to match(/ERROR: .* - ?#{error}$/)
|
72
70
|
end
|
73
71
|
|
74
72
|
it 'contains the transation id of the request' do
|
75
|
-
expect(subject.log_message(error: error, transaction_id: :transaction_id)).to include(
|
73
|
+
expect(subject.log_message(error: error, transaction_id: :transaction_id)).to include('ERROR: transaction_id')
|
76
74
|
end
|
77
75
|
end
|
78
76
|
end
|
@@ -3,8 +3,7 @@ class SiteHub
|
|
3
3
|
module Logging
|
4
4
|
describe LogEntry do
|
5
5
|
describe '#initialize' do
|
6
|
-
|
7
|
-
let(:time){Time.now}
|
6
|
+
let(:time) { Time.now }
|
8
7
|
subject do
|
9
8
|
described_class.new(:message, time)
|
10
9
|
end
|
@@ -26,9 +25,7 @@ class SiteHub
|
|
26
25
|
expect(subject.time).to be(:current_time)
|
27
26
|
end
|
28
27
|
end
|
29
|
-
|
30
|
-
|
31
28
|
end
|
32
29
|
end
|
33
30
|
end
|
34
|
-
end
|
31
|
+
end
|
@@ -3,13 +3,11 @@ require 'sitehub/logging/log_stash'
|
|
3
3
|
class SiteHub
|
4
4
|
module Logging
|
5
5
|
describe LogStash do
|
6
|
-
|
7
6
|
it 'inherits Array' do
|
8
7
|
expect(subject).to be_a_kind_of(Array)
|
9
8
|
end
|
10
9
|
|
11
10
|
describe '#<<' do
|
12
|
-
|
13
11
|
it 'adds a LogEntry' do
|
14
12
|
allow(Time).to receive(:now).and_return(:current_time)
|
15
13
|
subject << :message
|
@@ -18,4 +16,4 @@ class SiteHub
|
|
18
16
|
end
|
19
17
|
end
|
20
18
|
end
|
21
|
-
end
|
19
|
+
end
|
@@ -1,9 +1,7 @@
|
|
1
1
|
require 'sitehub/logging/log_wrapper'
|
2
2
|
class SiteHub
|
3
3
|
module Logging
|
4
|
-
|
5
4
|
describe LogWrapper do
|
6
|
-
|
7
5
|
describe '#write' do
|
8
6
|
let(:logger) { double('logger') }
|
9
7
|
subject do
|
@@ -19,14 +17,12 @@ class SiteHub
|
|
19
17
|
end
|
20
18
|
|
21
19
|
context 'logger responds to write' do
|
22
|
-
|
23
20
|
it 'calls << when writing out the log' do
|
24
21
|
message = 'message'
|
25
22
|
expect(logger).to receive(:write).with(message)
|
26
23
|
subject.write(message)
|
27
24
|
end
|
28
25
|
end
|
29
|
-
|
30
26
|
end
|
31
27
|
end
|
32
28
|
end
|
@@ -19,9 +19,7 @@ class SiteHub
|
|
19
19
|
end
|
20
20
|
|
21
21
|
describe '#apply_middleware' do
|
22
|
-
|
23
22
|
context 'middleware defined' do
|
24
|
-
|
25
23
|
it 'wraps the supplied app in the middleware' do
|
26
24
|
subject.use middleware
|
27
25
|
result = subject.apply_middleware(:app)
|
@@ -61,9 +59,7 @@ class SiteHub
|
|
61
59
|
expect(block_passed).to be(true)
|
62
60
|
end
|
63
61
|
end
|
64
|
-
|
65
62
|
end
|
66
|
-
|
67
63
|
end
|
68
64
|
end
|
69
|
-
end
|
65
|
+
end
|
@@ -1,13 +1,11 @@
|
|
1
1
|
require 'sitehub/path_directive'
|
2
2
|
class SiteHub
|
3
3
|
describe PathDirective do
|
4
|
-
|
5
4
|
subject do
|
6
5
|
described_class.new(%r{/match}, '/path_template')
|
7
6
|
end
|
8
7
|
|
9
8
|
describe '#match?' do
|
10
|
-
|
11
9
|
context 'matcher applies' do
|
12
10
|
it 'returns true' do
|
13
11
|
expect(subject.match?('/match')).to eq(true)
|
@@ -26,7 +24,7 @@ class SiteHub
|
|
26
24
|
described_class.new(Regexp.new('http://www.upstream.com/orders/(.*)'), '/$1')
|
27
25
|
end
|
28
26
|
|
29
|
-
let(:url){'http://www.upstream.com/orders/123'}
|
27
|
+
let(:url) { 'http://www.upstream.com/orders/123' }
|
30
28
|
|
31
29
|
it 'uses the url to populate the path template' do
|
32
30
|
expect(subject.apply(url)).to eq('/123')
|
@@ -39,12 +37,11 @@ class SiteHub
|
|
39
37
|
|
40
38
|
describe '#path_template' do
|
41
39
|
it 'returns a duplicate of the path_template every time' do
|
42
|
-
version1
|
40
|
+
version1 = subject.path_template
|
41
|
+
version2 = subject.path_template
|
43
42
|
expect(version1).to eq(version2)
|
44
43
|
expect(version1).to_not be(version2)
|
45
44
|
end
|
46
45
|
end
|
47
|
-
|
48
46
|
end
|
49
|
-
|
50
|
-
end
|
47
|
+
end
|
@@ -10,7 +10,7 @@ class SiteHub
|
|
10
10
|
it 'leaves the key has a regexp' do
|
11
11
|
key = %r{/.*/}
|
12
12
|
value = '/'
|
13
|
-
expect(described_class.new(key => value)).to eq([PathDirective.new(key,value)])
|
13
|
+
expect(described_class.new(key => value)).to eq([PathDirective.new(key, value)])
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -18,20 +18,20 @@ class SiteHub
|
|
18
18
|
it 'converts the key to a regexp' do
|
19
19
|
key = 'string'
|
20
20
|
value = '/'
|
21
|
-
expect(described_class.new(key => value)).to eq([PathDirective.new(Regexp.new(key),value)])
|
21
|
+
expect(described_class.new(key => value)).to eq([PathDirective.new(Regexp.new(key), value)])
|
22
22
|
end
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
26
|
describe '#find' do
|
27
|
-
let(:matcher){Regexp.new('/orders/(.*)')}
|
28
|
-
let(:path_template){'/orders/$1'}
|
27
|
+
let(:matcher) { Regexp.new('/orders/(.*)') }
|
28
|
+
let(:path_template) { '/orders/$1' }
|
29
29
|
subject do
|
30
30
|
described_class.new(matcher => path_template)
|
31
31
|
end
|
32
32
|
context 'url matches matcher' do
|
33
33
|
it 'returns the path directive' do
|
34
|
-
expect(subject.find('http://url.com/orders/123')).to eq(PathDirective.new(matcher,path_template))
|
34
|
+
expect(subject.find('http://url.com/orders/123')).to eq(PathDirective.new(matcher, path_template))
|
35
35
|
end
|
36
36
|
end
|
37
37
|
context 'url does not matches matcher' do
|
@@ -39,7 +39,6 @@ class SiteHub
|
|
39
39
|
expect(subject.find('http://url.com/mismatch')).to eq(nil)
|
40
40
|
end
|
41
41
|
end
|
42
|
-
|
43
42
|
end
|
44
43
|
end
|
45
|
-
end
|
44
|
+
end
|
@@ -2,9 +2,8 @@ require 'sitehub/request_mapping'
|
|
2
2
|
|
3
3
|
class SiteHub
|
4
4
|
describe RequestMapping do
|
5
|
-
|
6
5
|
describe '#initialize' do
|
7
|
-
let(:mapped_url){'http://downstream_url'}
|
6
|
+
let(:mapped_url) { 'http://downstream_url' }
|
8
7
|
subject do
|
9
8
|
described_class.new(source_url: 'http://upstream.com/articles/123',
|
10
9
|
mapped_url: mapped_url,
|
@@ -64,8 +63,6 @@ class SiteHub
|
|
64
63
|
expect(subject.computed_uri).to eq('http://downstream_url/articles?param=value')
|
65
64
|
end
|
66
65
|
end
|
67
|
-
|
68
|
-
|
69
66
|
end
|
70
67
|
end
|
71
|
-
end
|
68
|
+
end
|
@@ -1,36 +1,31 @@
|
|
1
1
|
class SiteHub
|
2
|
-
|
3
2
|
describe ReverseProxy do
|
4
|
-
|
5
3
|
include_context :middleware_test
|
6
4
|
|
5
|
+
let(:mapped_path) { '/orders' }
|
6
|
+
let(:user_facing_app_url) { "http://example.org#{mapped_path}" }
|
7
7
|
|
8
|
-
let(:
|
9
|
-
let(:
|
8
|
+
let(:downstream_mapping) { 'https://downstream.com/app1/orders' }
|
9
|
+
let(:downstream_location) { "#{downstream_mapping}/123/confirmation" }
|
10
10
|
|
11
|
+
let(:request_mapping) do
|
12
|
+
RequestMapping.new source_url: "#{user_facing_app_url}/123/payment",
|
13
|
+
mapped_url: downstream_mapping,
|
14
|
+
mapped_path: mapped_path
|
15
|
+
end
|
11
16
|
|
12
|
-
let(:downstream_mapping){'https://downstream.com/app1/orders'}
|
13
|
-
let(:downstream_location){"#{downstream_mapping}/123/confirmation"}
|
14
|
-
let(:request_mapping){RequestMapping.new source_url: "#{user_facing_app_url}/123/payment", mapped_url: downstream_mapping, mapped_path: mapped_path}
|
15
17
|
let(:app) do
|
16
|
-
proc{downstream_response}
|
18
|
+
proc { downstream_response }
|
17
19
|
end
|
18
|
-
let(:downstream_response){Rack::Response.new('downstream', 200,
|
20
|
+
let(:downstream_response) { Rack::Response.new('downstream', 200, 'header1' => 'header1') }
|
19
21
|
|
20
|
-
|
21
|
-
|
22
|
-
#end
|
23
|
-
|
24
|
-
subject(:reverse_proxy){described_class.new(app, [])}
|
25
|
-
let(:env){{REQUEST_MAPPING => request_mapping}}
|
22
|
+
subject(:reverse_proxy) { described_class.new(app, []) }
|
23
|
+
let(:env) { { REQUEST_MAPPING => request_mapping } }
|
26
24
|
|
27
25
|
describe '#call' do
|
28
|
-
|
29
|
-
|
30
|
-
|
31
26
|
subject(:response) do
|
32
27
|
status, headers, body = reverse_proxy.call(env).to_a
|
33
|
-
Rack::Response.new(body,status, headers)
|
28
|
+
Rack::Response.new(body, status, headers)
|
34
29
|
end
|
35
30
|
|
36
31
|
it 'copies the downstream body in to the response' do
|
@@ -49,7 +44,11 @@ class SiteHub
|
|
49
44
|
context 'downstream response contains a cookie' do
|
50
45
|
it 'rewrites it to use the upstream domain' do
|
51
46
|
downstream_response.set_cookie('downstream.cookie', domain: '.downstream.com', value: 'value')
|
52
|
-
|
47
|
+
|
48
|
+
expect(reverse_proxy)
|
49
|
+
.to receive(:rewrite_cookies)
|
50
|
+
.with(downstream_response.headers, substitute_domain: URI(request_mapping.source_url).host)
|
51
|
+
|
53
52
|
reverse_proxy.call(env)
|
54
53
|
end
|
55
54
|
end
|
@@ -64,42 +63,49 @@ class SiteHub
|
|
64
63
|
end
|
65
64
|
end
|
66
65
|
|
67
|
-
#Location, Content-Location and URI
|
66
|
+
# Location, Content-Location and URI
|
68
67
|
it 'rewrites the Location header' do
|
69
68
|
downstream_response.headers[HttpHeaders::LOCATION_HEADER] = downstream_location
|
70
|
-
|
69
|
+
|
70
|
+
expect(reverse_proxy)
|
71
|
+
.to receive(:interpolate_location)
|
72
|
+
.with(downstream_location, request_mapping.source_url)
|
73
|
+
.and_return(:interpolated_location)
|
74
|
+
|
71
75
|
reverse_proxy.call(env)
|
72
76
|
expect(downstream_response.headers[HttpHeaders::LOCATION_HEADER]).to eq(:interpolated_location)
|
73
77
|
end
|
74
|
-
|
75
78
|
end
|
76
79
|
|
77
80
|
describe '#interpolate_location' do
|
78
81
|
it 'changes the domain' do
|
79
|
-
expect(reverse_proxy.interpolate_location(downstream_location, request_mapping.source_url)).to eq(
|
82
|
+
expect(reverse_proxy.interpolate_location(downstream_location, request_mapping.source_url)).to eq('http://example.org/app1/orders/123/confirmation')
|
80
83
|
end
|
81
84
|
|
82
85
|
context 'there is a directive that applies' do
|
83
86
|
context 'matcher is a regexp' do
|
84
87
|
subject do
|
85
|
-
directive = {%r{#{downstream_mapping}/(.*)/confirmation} => '/confirmation/$1'}
|
86
|
-
described_class.new(inner_app,directive)
|
88
|
+
directive = { %r{#{downstream_mapping}/(.*)/confirmation} => '/confirmation/$1' }
|
89
|
+
described_class.new(inner_app, directive)
|
87
90
|
end
|
88
91
|
it 'changes the path' do
|
89
|
-
expect(subject.interpolate_location(downstream_location, request_mapping.source_url)).to eq(
|
92
|
+
expect(subject.interpolate_location(downstream_location, request_mapping.source_url)).to eq('http://example.org/confirmation/123')
|
90
93
|
end
|
91
94
|
end
|
92
95
|
|
93
96
|
context 'matcher is a string' do
|
97
|
+
let(:downstream_url) { 'http://downstream.com/confirmation' }
|
94
98
|
subject do
|
95
|
-
directive = {
|
96
|
-
described_class.new(inner_app,directive)
|
99
|
+
directive = { downstream_url => '/congratulations' }
|
100
|
+
described_class.new(inner_app, directive)
|
97
101
|
end
|
98
102
|
it 'changes the path' do
|
99
|
-
|
103
|
+
actual = subject.interpolate_location(downstream_url, request_mapping.source_url)
|
104
|
+
expected = 'http://example.org/congratulations'
|
105
|
+
expect(actual).to eq(expected)
|
100
106
|
end
|
101
107
|
end
|
102
108
|
end
|
103
109
|
end
|
104
110
|
end
|
105
|
-
end
|
111
|
+
end
|
@@ -2,9 +2,9 @@ require 'sitehub/transaction_id'
|
|
2
2
|
|
3
3
|
class SiteHub
|
4
4
|
describe TransactionId do
|
5
|
-
let(:transaction_id){Constants::RackHttpHeaderKeys::TRANSACTION_ID}
|
5
|
+
let(:transaction_id) { Constants::RackHttpHeaderKeys::TRANSACTION_ID }
|
6
6
|
subject do
|
7
|
-
described_class.new(
|
7
|
+
described_class.new(proc {})
|
8
8
|
end
|
9
9
|
it 'adds a unique identifier to the request' do
|
10
10
|
uuid = UUID.generate(:compact)
|
@@ -18,7 +18,7 @@ class SiteHub
|
|
18
18
|
context 'transaction id header already exists' do
|
19
19
|
it 'leaves it intact' do
|
20
20
|
expect(UUID).to_not receive(:generate)
|
21
|
-
env = {transaction_id => :exiting_id}
|
21
|
+
env = { transaction_id => :exiting_id }
|
22
22
|
subject.call(env)
|
23
23
|
|
24
24
|
expect(env[transaction_id]).to eq(:exiting_id)
|
data/spec/sitehub_spec.rb
CHANGED
@@ -1,5 +1,4 @@
|
|
1
1
|
describe SiteHub do
|
2
|
-
|
3
2
|
describe '::build' do
|
4
3
|
it 'gives you a configure sitehub to run in your config.ru' do
|
5
4
|
allow_any_instance_of(SiteHub::Builder).to receive(:build).and_return(:sitehub)
|
@@ -7,13 +6,12 @@ describe SiteHub do
|
|
7
6
|
end
|
8
7
|
it 'passes your block on a sitehub builder' do
|
9
8
|
block_called = false
|
10
|
-
block =
|
9
|
+
block = proc do
|
11
10
|
block_called = true
|
12
11
|
end
|
13
12
|
|
14
13
|
described_class.build(&block)
|
15
14
|
expect(block_called).to eq(true)
|
16
15
|
end
|
17
|
-
|
18
16
|
end
|
19
|
-
end
|
17
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Async
|
2
|
+
class Middleware
|
3
|
+
def initialize(app)
|
4
|
+
@app = app
|
5
|
+
end
|
6
|
+
|
7
|
+
def last_response
|
8
|
+
callback.response
|
9
|
+
end
|
10
|
+
|
11
|
+
def callback
|
12
|
+
@callback ||= Callback.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def call(env)
|
16
|
+
env['async.callback'] = callback
|
17
|
+
|
18
|
+
catch(:async) do
|
19
|
+
@app.call env
|
20
|
+
end
|
21
|
+
|
22
|
+
[200, {}, []]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Async
|
2
|
+
class ResponseHandler < EM::DefaultDeferrable
|
3
|
+
attr_reader :last_response, :callback_args
|
4
|
+
|
5
|
+
alias arg callback_args
|
6
|
+
|
7
|
+
def succeed(arg)
|
8
|
+
sitehub_response = arg[:downstream_response]
|
9
|
+
instance_variable_set(:@arg, arg)
|
10
|
+
status, headers, body = *sitehub_response.to_a
|
11
|
+
rack_response = Rack::Response.new(body, status, headers)
|
12
|
+
instance_variable_set(:@last_response, rack_response)
|
13
|
+
EM.stop
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -1,25 +1,17 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
cookies
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
1
|
+
module Rack
|
2
|
+
class Response
|
3
|
+
def cookies
|
4
|
+
cookie_key_value_array.each_with_object({}) do |cookie_key_value, cookies|
|
5
|
+
name_value_array = cookie_key_value.delete_at(0)
|
6
|
+
name, value = *name_value_array
|
7
|
+
data = cookie_key_value.collect { |pair| [pair[0].to_sym, pair[1]] }.to_h
|
8
|
+
cookies[name] = { value: value }.merge(data)
|
9
|
+
cookies
|
10
|
+
end
|
10
11
|
end
|
11
|
-
cookies
|
12
|
-
end
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
header['Set-Cookie'].lines.collect { |line| line.scan(/([\.\w]+)=([\.\w]+)/) }.each do |cookie_definition_array|
|
17
|
-
name_value_array = cookie_definition_array.delete_at(0)
|
18
|
-
name = name_value_array.first
|
19
|
-
value = name_value_array.last
|
20
|
-
data = cookie_definition_array.collect { |pair| [pair[0].to_sym, pair[1]] }.to_h
|
21
|
-
cookies[name] = {value: value}.merge(data)
|
13
|
+
def cookie_key_value_array
|
14
|
+
header['Set-Cookie'].lines.collect { |line| line.scan(%r{([\.\w]+)=([\.\w/]+)}) }
|
22
15
|
end
|
23
|
-
cookies
|
24
16
|
end
|
25
|
-
end
|
17
|
+
end
|
@@ -1,69 +1,14 @@
|
|
1
|
+
require_relative '../async'
|
1
2
|
shared_context :async do
|
2
|
-
class Callback
|
3
|
-
attr_reader :response
|
4
|
-
|
5
|
-
def call *args
|
6
|
-
status, headers, body = *args.flatten.to_a
|
7
|
-
@response = Rack::Response.new(body, status, headers)
|
8
|
-
EventMachine.stop if EventMachine.reactor_running?
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
3
|
def callback
|
13
|
-
@callback ||= Callback.new
|
4
|
+
@callback ||= Async::Callback.new
|
14
5
|
end
|
15
6
|
|
16
7
|
def async_response_handler
|
17
|
-
@async_response_handler
|
18
|
-
instance_double(EM::DefaultDeferrable).tap do |handler|
|
19
|
-
allow(handler).to receive(:succeed) do |arg|
|
20
|
-
sitehub_response = arg[:downstream_response]
|
21
|
-
handler.instance_variable_set(:@arg, arg)
|
22
|
-
sitehub_response = sitehub_response.to_a
|
23
|
-
handler.instance_variable_set(:@last_response, Rack::Response.new(sitehub_response[2], sitehub_response[0], sitehub_response[1]))
|
24
|
-
EM.stop
|
25
|
-
end
|
26
|
-
|
27
|
-
def handler.last_response
|
28
|
-
@last_response
|
29
|
-
end
|
30
|
-
|
31
|
-
def handler.callback_args
|
32
|
-
@arg
|
33
|
-
end
|
34
|
-
end
|
35
|
-
end
|
8
|
+
@async_response_handler = Async::ResponseHandler.new
|
36
9
|
end
|
37
10
|
|
38
11
|
def last_response
|
39
12
|
app.last_response
|
40
13
|
end
|
41
|
-
|
42
|
-
def async_middleware
|
43
|
-
Class.new do
|
44
|
-
def initialize app
|
45
|
-
@app = app
|
46
|
-
end
|
47
|
-
|
48
|
-
def last_response
|
49
|
-
callback.response
|
50
|
-
end
|
51
|
-
|
52
|
-
def callback
|
53
|
-
@callback ||= Callback.new
|
54
|
-
end
|
55
|
-
|
56
|
-
|
57
|
-
def call env
|
58
|
-
|
59
|
-
env['async.callback'] = callback
|
60
|
-
|
61
|
-
catch(:async) do
|
62
|
-
@app.call env
|
63
|
-
end
|
64
|
-
|
65
|
-
[200, {}, []]
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
69
14
|
end
|
@@ -1,51 +1,49 @@
|
|
1
1
|
shared_context :middleware_test do
|
2
|
-
|
3
2
|
include_context :rack_test
|
4
3
|
|
5
|
-
let(:inner_app)
|
6
|
-
proc{[200, {}, []]}
|
7
|
-
|
4
|
+
let(:inner_app) do
|
5
|
+
proc { [200, {}, []] }
|
6
|
+
end
|
8
7
|
|
9
8
|
subject(:app) do
|
10
9
|
described_class.new(inner_app)
|
11
10
|
end
|
12
11
|
|
13
|
-
def collect_middleware
|
12
|
+
def collect_middleware(rack_app)
|
14
13
|
middleware = [rack_app]
|
15
|
-
while rack_app = rack_app.instance_variable_get(:@app)
|
14
|
+
while (rack_app = rack_app.instance_variable_get(:@app))
|
16
15
|
middleware << rack_app
|
17
16
|
end
|
18
17
|
middleware
|
19
18
|
end
|
20
19
|
|
21
|
-
|
22
|
-
def find_middleware rack_app, clazz
|
20
|
+
def find_middleware(rack_app, clazz)
|
23
21
|
return rack_app if rack_app.is_a?(clazz)
|
24
|
-
collect_middleware(rack_app).find{|middleware| middleware.is_a?(clazz)}
|
22
|
+
collect_middleware(rack_app).find { |middleware| middleware.is_a?(clazz) }
|
25
23
|
end
|
26
24
|
|
27
|
-
RSpec::Matchers.define :be_using do |expected, *
|
25
|
+
RSpec::Matchers.define :be_using do |expected, *_args|
|
28
26
|
match do |actual|
|
29
|
-
|
27
|
+
!find_middleware(actual, expected).nil?
|
30
28
|
end
|
31
29
|
end
|
32
30
|
|
33
31
|
def create_middleware
|
34
32
|
Class.new do
|
35
33
|
attr_reader :app, :arg
|
36
|
-
def initialize
|
37
|
-
@app
|
38
|
-
|
34
|
+
def initialize(app, arg = nil, &block)
|
35
|
+
@app = app
|
36
|
+
@arg = arg
|
37
|
+
yield if block
|
39
38
|
end
|
40
39
|
|
41
|
-
def call
|
40
|
+
def call(env)
|
42
41
|
@app.call env
|
43
42
|
end
|
44
43
|
end
|
45
|
-
|
46
44
|
end
|
47
45
|
|
48
46
|
let(:middleware) do
|
49
47
|
create_middleware
|
50
48
|
end
|
51
|
-
end
|
49
|
+
end
|
@@ -3,10 +3,10 @@ shared_context :rack_test do
|
|
3
3
|
include Rack::Test::Methods
|
4
4
|
|
5
5
|
def env
|
6
|
-
@env||={}
|
6
|
+
@env ||= {}
|
7
7
|
end
|
8
8
|
|
9
9
|
before :each do |example|
|
10
|
-
@env = {'async.callback' => callback} if example.metadata[:async]
|
10
|
+
@env = { 'async.callback' => callback } if example.metadata[:async]
|
11
11
|
end
|
12
|
-
end
|
12
|
+
end
|