alephant-broker 0.0.3 → 0.1.0
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/alephant-broker.gemspec +1 -0
- data/lib/alephant/broker.rb +2 -3
- data/lib/alephant/broker/app.rb +2 -8
- data/lib/alephant/broker/app/rack.rb +5 -5
- data/lib/alephant/broker/call_environment.rb +51 -0
- data/lib/alephant/broker/errors/invalid_asset_id.rb +11 -0
- data/lib/alephant/broker/models/request.rb +16 -35
- data/lib/alephant/broker/models/request/error_request.rb +11 -0
- data/lib/alephant/broker/models/request/get_request.rb +38 -0
- data/lib/alephant/broker/models/request/notfound_request.rb +11 -0
- data/lib/alephant/broker/models/request/post_request.rb +46 -0
- data/lib/alephant/broker/models/request/status_request.rb +11 -0
- data/lib/alephant/broker/models/request_factory.rb +26 -0
- data/lib/alephant/broker/models/request_handler.rb +26 -3
- data/lib/alephant/broker/models/response/asset_response.rb +0 -4
- data/lib/alephant/broker/models/response/batch_response.rb +58 -0
- data/lib/alephant/broker/models/response_factory.rb +3 -0
- data/lib/alephant/broker/version.rb +1 -1
- data/spec/asset_response_spec.rb +44 -14
- data/spec/batch_response_spec.rb +85 -0
- data/spec/get_request_spec.rb +72 -0
- data/spec/post_request_spec.rb +49 -0
- data/spec/rack_spec.rb +21 -9
- data/spec/response_factory_spec.rb +34 -8
- data/spec/spec_helper.rb +3 -3
- metadata +32 -4
- data/spec/request_spec.rb +0 -51
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88c15819c22cfcde769e9b1b1406d9563ddd11f8
|
4
|
+
data.tar.gz: f1ed322acae0dc5740f6a965e3d790e1fca99dfd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3360481c1f7707c893d55635660cf3a5c56894c71aba9d87d80e73c549338ed47b9cede9a36233dbe5f0459b8405d7dbd39824819b4f2d42fcfc06aba0448c8
|
7
|
+
data.tar.gz: 2192c4157e16662cf51d26645d9cb0e9c1f859d487669926a87ab68bba3a78046de9eb49cc1cf8fa2dba60db5e579baf7c5e265b8cf2a3a5944119baa5913600
|
data/alephant-broker.gemspec
CHANGED
@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.add_development_dependency "bundler", "~> 1.5"
|
30
30
|
spec.add_development_dependency "rake"
|
31
31
|
spec.add_development_dependency "rack-test"
|
32
|
+
spec.add_development_dependency "request_store"
|
32
33
|
|
33
34
|
spec.add_runtime_dependency "alephant-lookup"
|
34
35
|
spec.add_runtime_dependency "alephant-cache"
|
data/lib/alephant/broker.rb
CHANGED
@@ -4,9 +4,8 @@ require "alephant/broker/models/request_handler"
|
|
4
4
|
module Alephant
|
5
5
|
module Broker
|
6
6
|
|
7
|
-
def self.handle(
|
8
|
-
|
9
|
-
@@request_handler.process(request)
|
7
|
+
def self.handle(config = {})
|
8
|
+
RequestHandler.new(config).process
|
10
9
|
end
|
11
10
|
end
|
12
11
|
|
data/lib/alephant/broker/app.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
$: << File.dirname(__FILE__)
|
2
2
|
|
3
3
|
require 'alephant/broker'
|
4
|
-
require 'alephant/broker/models/request'
|
5
4
|
require 'alephant/logger'
|
6
5
|
|
7
6
|
module Alephant
|
@@ -13,14 +12,9 @@ module Alephant
|
|
13
12
|
@config = config
|
14
13
|
end
|
15
14
|
|
16
|
-
def handle
|
17
|
-
Alephant::Broker.handle(
|
15
|
+
def handle
|
16
|
+
Alephant::Broker.handle(@config)
|
18
17
|
end
|
19
|
-
|
20
|
-
def request_from(path, querystring)
|
21
|
-
Request.new(path, querystring)
|
22
|
-
end
|
23
|
-
|
24
18
|
end
|
25
19
|
end
|
26
20
|
end
|
@@ -1,23 +1,23 @@
|
|
1
1
|
$: << File.dirname(__FILE__)
|
2
2
|
|
3
3
|
require 'alephant/broker/app'
|
4
|
+
require 'alephant/broker/call_environment'
|
4
5
|
|
5
6
|
module Alephant
|
6
7
|
module Broker
|
7
8
|
class RackApplication < Application
|
8
9
|
|
9
10
|
def call(env)
|
10
|
-
|
11
|
-
|
12
|
-
)
|
11
|
+
RequestStore.store[:env] ||= CallEnvironment.new(env)
|
12
|
+
response = handle
|
13
13
|
send response
|
14
14
|
end
|
15
15
|
|
16
16
|
def send(response)
|
17
17
|
[
|
18
18
|
response.status,
|
19
|
-
{"Content-Type" => response.content_type},
|
20
|
-
[response.content.to_s]
|
19
|
+
{ "Content-Type" => response.content_type },
|
20
|
+
[ response.content.to_s ]
|
21
21
|
]
|
22
22
|
end
|
23
23
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Alephant
|
2
|
+
module Broker
|
3
|
+
class CallEnvironment
|
4
|
+
include Logger
|
5
|
+
attr_reader :settings
|
6
|
+
|
7
|
+
def initialize(env)
|
8
|
+
@settings = env
|
9
|
+
end
|
10
|
+
|
11
|
+
def method
|
12
|
+
@settings['REQUEST_METHOD']
|
13
|
+
end
|
14
|
+
|
15
|
+
def post?
|
16
|
+
@settings['REQUEST_METHOD'] == 'POST'
|
17
|
+
end
|
18
|
+
|
19
|
+
def get?
|
20
|
+
@settings['REQUEST_METHOD'] == 'GET'
|
21
|
+
end
|
22
|
+
|
23
|
+
def query
|
24
|
+
@settings['QUERY_STRING']
|
25
|
+
end
|
26
|
+
|
27
|
+
def path
|
28
|
+
@settings['PATH_INFO']
|
29
|
+
end
|
30
|
+
|
31
|
+
def data
|
32
|
+
parse(rack_input) if post?
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def rack_input
|
38
|
+
(@settings['rack.input'].read).tap { @settings['rack.input'].rewind } # http://rack.rubyforge.org/doc/SPEC.html
|
39
|
+
end
|
40
|
+
|
41
|
+
def parse(json)
|
42
|
+
begin
|
43
|
+
JSON.parse(json)
|
44
|
+
rescue JSON::ParserError => e
|
45
|
+
logger.info("Broker.environment#data: ParserError")
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -4,8 +4,7 @@ module Alephant
|
|
4
4
|
module Broker
|
5
5
|
class Request
|
6
6
|
include Logger
|
7
|
-
|
8
|
-
attr_reader :type, :component_id, :options, :extension, :content_type
|
7
|
+
attr_reader :type
|
9
8
|
|
10
9
|
DEFAULT_EXTENSION = :html
|
11
10
|
|
@@ -14,39 +13,9 @@ module Alephant
|
|
14
13
|
:json => 'application/json'
|
15
14
|
}
|
16
15
|
|
17
|
-
def initialize(
|
18
|
-
request
|
19
|
-
|
20
|
-
when "component"
|
21
|
-
logger.info("Broker.request: Type: component, Asset ID: #{request[:component_id]}, Options: #{request[:options].inspect}")
|
22
|
-
@type = :asset
|
23
|
-
|
24
|
-
@component_id = request[:component_id]
|
25
|
-
raise Errors::InvalidAssetId.new("No Asset ID specified") if @component_id.nil?
|
26
|
-
|
27
|
-
@options = request[:options]
|
28
|
-
@extension = request[:extension]
|
29
|
-
@content_type = @@extension_mapping[@extension.to_sym] || @@extension_mapping[DEFAULT_EXTENSION]
|
30
|
-
when "status"
|
31
|
-
logger.info("Broker.request: Type: status")
|
32
|
-
@type = :status
|
33
|
-
else
|
34
|
-
logger.info("Broker.request: Type: notfound")
|
35
|
-
@type = :notfound
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
private
|
40
|
-
|
41
|
-
def request_components(path, query_string)
|
42
|
-
request_parts = path.split('/')
|
43
|
-
extension = path.split('.')[1] ? path.split('.')[1].to_sym : DEFAULT_EXTENSION
|
44
|
-
{
|
45
|
-
:type => request_parts[1],
|
46
|
-
:component_id => (request_parts[2] || '').split('.')[0],
|
47
|
-
:extension => extension,
|
48
|
-
:options => options_from(query_string)
|
49
|
-
}
|
16
|
+
def initialize(request_type)
|
17
|
+
logger.info("Broker.request: Type: #{request_type}")
|
18
|
+
@type = request_type
|
50
19
|
end
|
51
20
|
|
52
21
|
def options_from(query_string)
|
@@ -55,6 +24,18 @@ module Alephant
|
|
55
24
|
object.tap { |o| o.store(key.to_sym, value) }
|
56
25
|
end
|
57
26
|
end
|
27
|
+
|
28
|
+
def get_type_from(request_parts)
|
29
|
+
request_parts[1]
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_extension_for(path)
|
33
|
+
path.split('.')[1] ? path.split('.')[1].to_sym : DEFAULT_EXTENSION
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_component_id_from(request_parts)
|
37
|
+
(request_parts[2] || '').split('.')[0]
|
38
|
+
end
|
58
39
|
end
|
59
40
|
end
|
60
41
|
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'alephant/broker/errors/invalid_asset_id'
|
2
|
+
require 'alephant/broker/models/request'
|
3
|
+
|
4
|
+
module Alephant
|
5
|
+
module Broker
|
6
|
+
class GetRequest < Request
|
7
|
+
attr_reader :type, :component_id, :extension, :options, :content_type
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
env = RequestStore.store[:env]
|
11
|
+
parse requested_components(env.path, env.query)
|
12
|
+
super(:asset)
|
13
|
+
end
|
14
|
+
|
15
|
+
def requested_components(path, query_string)
|
16
|
+
request_parts = path.split('/')
|
17
|
+
|
18
|
+
{
|
19
|
+
:type => get_type_from(request_parts),
|
20
|
+
:component_id => get_component_id_from(request_parts),
|
21
|
+
:extension => get_extension_for(path),
|
22
|
+
:options => options_from(query_string)
|
23
|
+
}
|
24
|
+
end
|
25
|
+
|
26
|
+
def parse(request)
|
27
|
+
@component_id = request[:component_id]
|
28
|
+
@extension = request[:extension]
|
29
|
+
@options = request[:options]
|
30
|
+
@content_type = @@extension_mapping[@extension.to_sym] || @@extension_mapping[DEFAULT_EXTENSION]
|
31
|
+
|
32
|
+
logger.info("Broker.request: Type: #{@type}, Asset ID: #{@component_id}, Options: #{@options.inspect}")
|
33
|
+
|
34
|
+
raise InvalidAssetId.new("No Asset ID specified") if @component_id.nil?
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'alephant/broker/models/request'
|
2
|
+
|
3
|
+
module Alephant
|
4
|
+
module Broker
|
5
|
+
class PostRequest < Request
|
6
|
+
attr_reader :type, :component_id, :options, :content_type
|
7
|
+
|
8
|
+
def initialize
|
9
|
+
@env = RequestStore.store[:env]
|
10
|
+
@content_type = 'application/json'
|
11
|
+
super(:batch)
|
12
|
+
end
|
13
|
+
|
14
|
+
def components
|
15
|
+
@requested_components ||= components_for @env.path
|
16
|
+
end
|
17
|
+
|
18
|
+
def set_component(id, options)
|
19
|
+
@component_id = id
|
20
|
+
@options = options
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def components_for(path)
|
26
|
+
request_parts = path.split('/')
|
27
|
+
|
28
|
+
{
|
29
|
+
:batch_id => batch_id,
|
30
|
+
:type => get_type_from(request_parts),
|
31
|
+
:component_id => get_component_id_from(request_parts)
|
32
|
+
}.merge! batched
|
33
|
+
end
|
34
|
+
|
35
|
+
def batch_id
|
36
|
+
@env.data['batch_id']
|
37
|
+
end
|
38
|
+
|
39
|
+
def batched
|
40
|
+
@env.data['components'].reduce({ :components => [] }) do |obj, component|
|
41
|
+
obj.tap { |o| o[:components].push(component) }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'alephant/broker/models/request/error_request.rb'
|
2
|
+
require 'alephant/broker/models/request/get_request.rb'
|
3
|
+
require 'alephant/broker/models/request/notfound_request.rb'
|
4
|
+
require 'alephant/broker/models/request/post_request.rb'
|
5
|
+
require 'alephant/broker/models/request/status_request.rb'
|
6
|
+
|
7
|
+
module Alephant
|
8
|
+
module Broker
|
9
|
+
class RequestFactory
|
10
|
+
def self.process(type)
|
11
|
+
case type
|
12
|
+
when :component
|
13
|
+
GetRequest.new
|
14
|
+
when :component_batch
|
15
|
+
PostRequest.new
|
16
|
+
when :status
|
17
|
+
StatusRequest.new
|
18
|
+
when :notfound
|
19
|
+
NotFoundRequest.new
|
20
|
+
when :error
|
21
|
+
ErrorRequest.new
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'alephant/broker/models/
|
1
|
+
require 'alephant/broker/models/request_factory'
|
2
2
|
require 'alephant/broker/models/response_factory'
|
3
3
|
|
4
4
|
module Alephant
|
@@ -7,18 +7,41 @@ module Alephant
|
|
7
7
|
include Logger
|
8
8
|
|
9
9
|
def initialize(config)
|
10
|
+
@env = RequestStore.store[:env]
|
11
|
+
@request = RequestFactory.process(request_type)
|
10
12
|
@response_factory = ResponseFactory.new(config)
|
11
13
|
end
|
12
14
|
|
13
|
-
def process
|
15
|
+
def process
|
14
16
|
begin
|
15
|
-
@response_factory.response_from(request)
|
17
|
+
@response_factory.response_from(@request)
|
16
18
|
rescue Exception => e
|
17
19
|
logger.info("Broker.requestHandler.process: Exception raised (#{e.message})")
|
18
20
|
@response_factory.response(500)
|
19
21
|
end
|
20
22
|
end
|
21
23
|
|
24
|
+
private
|
25
|
+
|
26
|
+
def request_type
|
27
|
+
case @env.path.split('/')[1]
|
28
|
+
when 'components'
|
29
|
+
component_type
|
30
|
+
when 'status'
|
31
|
+
:status
|
32
|
+
else
|
33
|
+
:notfound
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def component_type
|
38
|
+
case @env.method
|
39
|
+
when 'POST'
|
40
|
+
:component_batch
|
41
|
+
when 'GET'
|
42
|
+
:component
|
43
|
+
end
|
44
|
+
end
|
22
45
|
end
|
23
46
|
end
|
24
47
|
end
|
@@ -25,7 +25,6 @@ module Alephant
|
|
25
25
|
rescue Exception => e
|
26
26
|
set_error_for(e, 500)
|
27
27
|
end
|
28
|
-
|
29
28
|
end
|
30
29
|
|
31
30
|
private
|
@@ -39,9 +38,6 @@ module Alephant
|
|
39
38
|
def cache_id
|
40
39
|
@lookup.read(request.options).tap { |cache_id| raise InvalidCacheKey if cache_id.nil? }
|
41
40
|
end
|
42
|
-
|
43
41
|
end
|
44
42
|
end
|
45
43
|
end
|
46
|
-
|
47
|
-
|
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'alephant/logger'
|
2
|
+
|
3
|
+
module Alephant
|
4
|
+
module Broker
|
5
|
+
class BatchResponse
|
6
|
+
include Logger
|
7
|
+
attr_reader :status, :content_type, :content
|
8
|
+
|
9
|
+
def initialize(request, config)
|
10
|
+
@request = request
|
11
|
+
@config = config
|
12
|
+
@status = 200
|
13
|
+
@content_type = request.content_type
|
14
|
+
end
|
15
|
+
|
16
|
+
def process
|
17
|
+
@content = JSON.generate({ "batch_id" => batch_id, "components" => json })
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def json
|
24
|
+
get_components.each do |component|
|
25
|
+
id = component['component']
|
26
|
+
options = set_keys_to_symbols component.fetch('options', {})
|
27
|
+
|
28
|
+
@request.set_component(id, options)
|
29
|
+
|
30
|
+
asset = AssetResponse.new(@request, @config)
|
31
|
+
component.store('status', asset.status)
|
32
|
+
component.store('body', asset.content) if valid_status_for asset
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_keys_to_symbols(hash)
|
37
|
+
Hash[hash.map { |k,v| [k.to_sym, v] }]
|
38
|
+
end
|
39
|
+
|
40
|
+
def batch_id
|
41
|
+
@request.components.fetch(:batch_id)
|
42
|
+
end
|
43
|
+
|
44
|
+
def get_components
|
45
|
+
@request.components.fetch(:components) do |key|
|
46
|
+
logger.info("Broker::BatchResponse.process: Received request object but no valid key was found")
|
47
|
+
[]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def valid_status_for(asset)
|
52
|
+
asset.status == 200
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'alephant/broker/models/response'
|
2
2
|
require 'alephant/broker/models/response/asset_response'
|
3
|
+
require 'alephant/broker/models/response/batch_response'
|
3
4
|
|
4
5
|
module Alephant
|
5
6
|
module Broker
|
@@ -13,6 +14,8 @@ module Alephant
|
|
13
14
|
case request.type
|
14
15
|
when :asset
|
15
16
|
AssetResponse.new(request, @config)
|
17
|
+
when :batch
|
18
|
+
BatchResponse.new(request, @config).process
|
16
19
|
when :status
|
17
20
|
response(200)
|
18
21
|
when :notfound
|
data/spec/asset_response_spec.rb
CHANGED
@@ -1,21 +1,42 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Alephant::Broker::AssetResponse do
|
4
|
-
|
5
4
|
describe "#initialize(request, config)" do
|
6
|
-
let(:config) { { :lookup_table_name => 'test_table', :bucket_id => 'test_bucket', :path => 'test_path' } }
|
7
|
-
let(:request) { double("Alephant::Broker::Request", :component_id => 'test', :content_type => 'text/html', :options => {:variant => 'test_variant'} ) }
|
8
5
|
let(:location) { 'test_location' }
|
6
|
+
let(:config) {{
|
7
|
+
:lookup_table_name => 'test_table',
|
8
|
+
:bucket_id => 'test_bucket',
|
9
|
+
:path => 'test_path'
|
10
|
+
}}
|
11
|
+
let(:request) { double(
|
12
|
+
"Alephant::Broker::Request",
|
13
|
+
:component_id => 'test',
|
14
|
+
:content_type => 'text/html',
|
15
|
+
:options => { :variant => 'test_variant' }
|
16
|
+
)
|
17
|
+
}
|
9
18
|
|
10
|
-
before
|
19
|
+
before do
|
11
20
|
@lookup_table = double('Alephant::Lookup::LookupTable')
|
12
21
|
Alephant::Lookup.stub(:create).and_return(@lookup_table)
|
13
|
-
|
22
|
+
end
|
14
23
|
|
15
24
|
it "Should return the content from a successful cache lookup" do
|
16
|
-
allow(@lookup_table)
|
17
|
-
|
18
|
-
|
25
|
+
allow(@lookup_table)
|
26
|
+
.to receive(:read)
|
27
|
+
.with(request.options)
|
28
|
+
.and_return(location)
|
29
|
+
|
30
|
+
Alephant::Cache
|
31
|
+
.any_instance
|
32
|
+
.stub(:initialize)
|
33
|
+
|
34
|
+
Alephant::Cache
|
35
|
+
.any_instance
|
36
|
+
.stub(:get)
|
37
|
+
.with(location)
|
38
|
+
.and_return('Test cache content')
|
39
|
+
|
19
40
|
instance = Alephant::Broker::AssetResponse.new(request, config)
|
20
41
|
|
21
42
|
expect(instance.content).to eq('Test cache content')
|
@@ -23,8 +44,15 @@ describe Alephant::Broker::AssetResponse do
|
|
23
44
|
end
|
24
45
|
|
25
46
|
it "should return a 404 if lookup can't find a valid location" do
|
26
|
-
allow(@lookup_table)
|
27
|
-
|
47
|
+
allow(@lookup_table)
|
48
|
+
.to receive(:read)
|
49
|
+
.with(request.options)
|
50
|
+
.and_return(nil)
|
51
|
+
|
52
|
+
Alephant::Cache
|
53
|
+
.any_instance
|
54
|
+
.stub(:initialize)
|
55
|
+
|
28
56
|
instance = Alephant::Broker::AssetResponse.new(request, config)
|
29
57
|
|
30
58
|
expect(instance.content).to eq('Cache key not found based on component_id and options combination')
|
@@ -32,15 +60,17 @@ describe Alephant::Broker::AssetResponse do
|
|
32
60
|
end
|
33
61
|
|
34
62
|
it "should return a 500 for any other exceptions" do
|
35
|
-
allow(@lookup_table)
|
63
|
+
allow(@lookup_table)
|
64
|
+
.to receive(:read)
|
65
|
+
.with(request.options)
|
66
|
+
.and_raise(Exception)
|
67
|
+
|
36
68
|
instance = Alephant::Broker::AssetResponse.new(request, config)
|
37
69
|
|
38
70
|
expect(instance.status).to eq(500)
|
39
|
-
|
40
71
|
end
|
41
|
-
|
42
72
|
end
|
43
|
-
|
44
73
|
end
|
45
74
|
|
46
75
|
|
76
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Alephant::Broker::BatchResponse do
|
4
|
+
let (:config) {{
|
5
|
+
:lookup_table_name => 'test_table',
|
6
|
+
:bucket_id => 'test_bucket',
|
7
|
+
:path => 'test_path'
|
8
|
+
}}
|
9
|
+
|
10
|
+
let (:post_request) {
|
11
|
+
double(
|
12
|
+
'Alephant::Broker::PostRequest',
|
13
|
+
:options => {},
|
14
|
+
:type => :batch,
|
15
|
+
:content_type => 'application/json',
|
16
|
+
:set_component => nil,
|
17
|
+
:component_id => nil,
|
18
|
+
:components => {
|
19
|
+
:batch_id => :baz,
|
20
|
+
:components => [
|
21
|
+
{ 'component' => 'foo1', 'options' => { 'variant' => 'bar1' } },
|
22
|
+
{ 'component' => 'foo2', 'options' => { 'variant' => 'bar2' } }
|
23
|
+
]}
|
24
|
+
)
|
25
|
+
}
|
26
|
+
|
27
|
+
before do
|
28
|
+
@lookup_table = double('Alephant::Lookup::LookupTable', :read => 'test_location')
|
29
|
+
|
30
|
+
Alephant::Lookup
|
31
|
+
.stub(:create)
|
32
|
+
.and_return(@lookup_table)
|
33
|
+
|
34
|
+
Alephant::Cache
|
35
|
+
.any_instance
|
36
|
+
.stub(:initialize)
|
37
|
+
|
38
|
+
Alephant::Cache
|
39
|
+
.any_instance
|
40
|
+
.stub(:get)
|
41
|
+
.and_return('Test response')
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "#process" do
|
45
|
+
context "if a component is unrecognised" do
|
46
|
+
before(:each) do
|
47
|
+
Alephant::Cache
|
48
|
+
.any_instance
|
49
|
+
.stub(:get)
|
50
|
+
.and_raise(Alephant::Broker::InvalidCacheKey)
|
51
|
+
|
52
|
+
instance = Alephant::Broker::BatchResponse.new(post_request, config)
|
53
|
+
json = JSON.parse(instance.process.content)
|
54
|
+
@bad_component = json.fetch('components')[1]
|
55
|
+
end
|
56
|
+
|
57
|
+
it "set status to 404" do
|
58
|
+
expect(@bad_component['status']).to eq(404)
|
59
|
+
end
|
60
|
+
|
61
|
+
it "remove 'body' key" do
|
62
|
+
expect(@bad_component['body']).to eq(nil)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context "if a component is recognised" do
|
67
|
+
before(:each) do
|
68
|
+
@instance = Alephant::Broker::BatchResponse.new(post_request, config)
|
69
|
+
@content = @instance.process.content
|
70
|
+
@json = JSON.parse(@content)
|
71
|
+
end
|
72
|
+
|
73
|
+
it "set status to 200" do
|
74
|
+
@json.fetch('components').each do |component|
|
75
|
+
expect(component['status']).to eq(200)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
it "set @content to be JSON string containing retrieved components" do
|
80
|
+
compiled_json = '{"batch_id":"baz","components":[{"component":"foo1","options":{"variant":"bar1"},"status":200,"body":"Test response"},{"component":"foo2","options":{"variant":"bar2"},"status":200,"body":"Test response"}]}'
|
81
|
+
expect(@content).to eq(compiled_json)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Alephant::Broker::GetRequest do
|
4
|
+
subject { Alephant::Broker::GetRequest }
|
5
|
+
|
6
|
+
before(:each) do
|
7
|
+
subject.any_instance.stub(:initialize)
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#requested_components" do
|
11
|
+
it "returns hash of component parts" do
|
12
|
+
result = subject.new.requested_components('/foo/bar', 'baz=qux')
|
13
|
+
hash = {
|
14
|
+
:type => "foo",
|
15
|
+
:component_id => "bar",
|
16
|
+
:extension => :html,
|
17
|
+
:options => { :baz => "qux" }
|
18
|
+
}
|
19
|
+
|
20
|
+
expect(result).to eq(hash)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#parse" do
|
25
|
+
context "when component_id is nil" do
|
26
|
+
it "raise error" do
|
27
|
+
expect {
|
28
|
+
subject.new.parse :extension => :foobar
|
29
|
+
}.to raise_exception
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "when component_id is not nil" do
|
34
|
+
it "sets values for attr_reader's" do
|
35
|
+
request = {
|
36
|
+
:component_id => 'foo',
|
37
|
+
:extension => 'bar',
|
38
|
+
:options => 'baz'
|
39
|
+
}
|
40
|
+
|
41
|
+
instance = subject.new
|
42
|
+
instance.parse(request)
|
43
|
+
|
44
|
+
expect(instance.component_id).to eq('foo')
|
45
|
+
expect(instance.extension).to eq('bar')
|
46
|
+
expect(instance.options).to eq('baz')
|
47
|
+
end
|
48
|
+
|
49
|
+
context "and extension is recognised" do
|
50
|
+
it "sets appropriate value for instance attribute" do
|
51
|
+
request = { :extension => 'json', :component_id => 'foo' }
|
52
|
+
|
53
|
+
instance = subject.new
|
54
|
+
instance.parse(request)
|
55
|
+
|
56
|
+
expect(instance.content_type).to eq('application/json')
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
context "and extension is not recognised" do
|
61
|
+
it "sets default value for instance attribute" do
|
62
|
+
request = { :extension => 'foobar', :component_id => 'foo' }
|
63
|
+
|
64
|
+
instance = subject.new
|
65
|
+
instance.parse(request)
|
66
|
+
|
67
|
+
expect(instance.content_type).to eq('text/html')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Alephant::Broker::PostRequest do
|
4
|
+
subject { Alephant::Broker::PostRequest }
|
5
|
+
|
6
|
+
describe "#components" do
|
7
|
+
it "returns hash of component parts + sub components" do
|
8
|
+
components = [{
|
9
|
+
"component" => "qux",
|
10
|
+
"options" => { "variant" => "cor" }
|
11
|
+
}]
|
12
|
+
|
13
|
+
env = (Struct.new(:path, :data)).new("/foo/bar", {
|
14
|
+
'batch_id' => :foobar,
|
15
|
+
'components' => components
|
16
|
+
})
|
17
|
+
|
18
|
+
hash = {
|
19
|
+
:batch_id => :foobar,
|
20
|
+
:type => "foo",
|
21
|
+
:component_id => "bar",
|
22
|
+
:components => components
|
23
|
+
}
|
24
|
+
|
25
|
+
RequestStore
|
26
|
+
.stub(:store)
|
27
|
+
.and_return({
|
28
|
+
:env => env
|
29
|
+
})
|
30
|
+
|
31
|
+
instance = subject.new
|
32
|
+
expect(instance.components).to eq(hash)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "#set_component(id, options)" do
|
37
|
+
it "sets instance attribute values" do
|
38
|
+
subject
|
39
|
+
.any_instance
|
40
|
+
.stub(:initialize)
|
41
|
+
|
42
|
+
instance = subject.new
|
43
|
+
instance.set_component(:foo, :bar)
|
44
|
+
|
45
|
+
expect(instance.component_id).to eq(:foo)
|
46
|
+
expect(instance.options).to eq(:bar)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
data/spec/rack_spec.rb
CHANGED
@@ -2,20 +2,22 @@ ENV['RACK_ENV'] = 'test'
|
|
2
2
|
|
3
3
|
require 'rack/test'
|
4
4
|
require 'alephant/broker/app/rack'
|
5
|
+
require 'request_store'
|
5
6
|
|
6
7
|
RSpec.configure do |conf|
|
7
8
|
conf.include Rack::Test::Methods
|
8
9
|
end
|
9
10
|
|
10
|
-
describe 'Broker
|
11
|
+
describe 'Broker Rack Application' do
|
12
|
+
before do
|
13
|
+
RequestStore.store[:env] = nil
|
11
14
|
|
12
|
-
before {
|
13
15
|
@lookup_table = double('Alephant::Lookup::LookupTable')
|
14
16
|
Alephant::Lookup.stub(:create).and_return(@lookup_table)
|
15
17
|
|
16
18
|
Alephant::Cache.any_instance.stub(:initialize)
|
17
19
|
Alephant::Cache.any_instance.stub(:get).and_return('Test response')
|
18
|
-
|
20
|
+
end
|
19
21
|
|
20
22
|
def app
|
21
23
|
Alephant::Broker::RackApplication.new({
|
@@ -25,7 +27,7 @@ describe 'Broker rack app tests' do
|
|
25
27
|
})
|
26
28
|
end
|
27
29
|
|
28
|
-
it
|
30
|
+
it 'Tests status page' do
|
29
31
|
get '/status'
|
30
32
|
expect(last_response).to be_ok
|
31
33
|
expect(last_response.body).to eq('ok')
|
@@ -40,7 +42,7 @@ describe 'Broker rack app tests' do
|
|
40
42
|
it "Test asset data is returned" do
|
41
43
|
allow(@lookup_table).to receive(:read).and_return('some_location')
|
42
44
|
|
43
|
-
get '/
|
45
|
+
get '/components/test_component'
|
44
46
|
expect(last_response).to be_ok
|
45
47
|
expect(last_response.body).to eq('Test response')
|
46
48
|
end
|
@@ -49,7 +51,7 @@ describe 'Broker rack app tests' do
|
|
49
51
|
variant = {:variant => 'test_variant'}
|
50
52
|
allow(@lookup_table).to receive(:read).with(variant).and_return('some_location')
|
51
53
|
|
52
|
-
get '/
|
54
|
+
get '/components/test_component?variant=test_variant'
|
53
55
|
expect(last_response).to be_ok
|
54
56
|
expect(last_response.body).to eq('Test response')
|
55
57
|
end
|
@@ -57,16 +59,26 @@ describe 'Broker rack app tests' do
|
|
57
59
|
it "Tests 404 when lookup doesn't return a valid location" do
|
58
60
|
allow(@lookup_table).to receive(:read).and_return(nil)
|
59
61
|
|
60
|
-
get '/
|
62
|
+
get '/components/test_component'
|
61
63
|
expect(last_response.status).to eq(404)
|
62
|
-
|
63
64
|
end
|
64
65
|
|
65
66
|
it "Tests 500 when exception is raised in application" do
|
66
67
|
allow(@lookup_table).to receive(:read).and_raise(Exception)
|
67
68
|
|
68
|
-
get '/
|
69
|
+
get '/components/test_component'
|
69
70
|
expect(last_response.status).to eq(500)
|
70
71
|
end
|
71
72
|
|
73
|
+
it "Test batch asset data is returned" do
|
74
|
+
allow(@lookup_table).to receive(:read).and_return('some_location')
|
75
|
+
|
76
|
+
json = '{"batch_id":"baz","components":[{"component":"ni_council_results_table"},{"component":"ni_council_results_table"}]}'
|
77
|
+
compiled_json = '{"batch_id":"baz","components":[{"component":"ni_council_results_table","status":200,"body":"Test response"},{"component":"ni_council_results_table","status":200,"body":"Test response"}]}'
|
78
|
+
|
79
|
+
post '/components/batch', json, "CONTENT_TYPE" => "application/json"
|
80
|
+
|
81
|
+
expect(last_response).to be_ok
|
82
|
+
expect(last_response.body).to eq(compiled_json)
|
83
|
+
end
|
72
84
|
end
|
@@ -1,35 +1,61 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Alephant::Broker::ResponseFactory do
|
4
|
-
|
5
4
|
describe "#response_from(request)" do
|
6
5
|
let (:request) { double("Alephant::Broker::Request") }
|
6
|
+
let (:post_request) { double("Alephant::Broker::PostRequest") }
|
7
7
|
|
8
|
-
it "should return
|
8
|
+
it "should return asset response" do
|
9
9
|
instance = Alephant::Broker::ResponseFactory.new({})
|
10
10
|
allow(request).to receive(:type).and_return(:asset)
|
11
11
|
|
12
|
-
Alephant::Broker::AssetResponse
|
13
|
-
|
12
|
+
Alephant::Broker::AssetResponse
|
13
|
+
.any_instance
|
14
|
+
.stub(:initialize)
|
15
|
+
.with(request, {})
|
16
|
+
|
17
|
+
expect(instance.response_from(request))
|
18
|
+
.to be_a Alephant::Broker::AssetResponse
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should return batched response" do
|
22
|
+
instance = Alephant::Broker::ResponseFactory.new({})
|
23
|
+
allow(post_request).to receive(:type).and_return(:batch)
|
24
|
+
allow(post_request).to receive(:content_type).and_return('application/json')
|
25
|
+
allow(post_request).to receive(:set_component)
|
26
|
+
allow(post_request).to receive(:components).and_return({
|
27
|
+
:batch_id => 'baz',
|
28
|
+
:components => [
|
29
|
+
{ 'component' => 'foo1', 'variant' => 'bar1' },
|
30
|
+
{ 'component' => 'foo2', 'variant' => 'bar2' }
|
31
|
+
]
|
32
|
+
})
|
33
|
+
|
34
|
+
Alephant::Broker::AssetResponse
|
35
|
+
.any_instance
|
36
|
+
.stub(:initialize)
|
37
|
+
.with(post_request, {})
|
38
|
+
|
39
|
+
expect(instance.response_from(post_request))
|
40
|
+
.to be_a Alephant::Broker::BatchResponse
|
14
41
|
end
|
15
42
|
|
16
|
-
it "should return
|
43
|
+
it "should return status response" do
|
17
44
|
allow(request).to receive(:type).and_return(:status)
|
18
45
|
response = subject.response_from(request)
|
19
46
|
expect(response.status).to eq(200)
|
20
47
|
end
|
21
48
|
|
22
|
-
it "should return
|
49
|
+
it "should return 404 response" do
|
23
50
|
allow(request).to receive(:type).and_return(:notfound)
|
24
51
|
response = subject.response_from(request)
|
25
52
|
expect(response.status).to eq(404)
|
26
53
|
end
|
27
54
|
|
28
|
-
it "should return
|
55
|
+
it "should return 500 response" do
|
29
56
|
allow(request).to receive(:type).and_return(:error)
|
30
57
|
response = subject.response_from(request)
|
31
58
|
expect(response.status).to eq(500)
|
32
59
|
end
|
33
|
-
|
34
60
|
end
|
35
61
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: alephant-broker
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Steven Jack
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-03-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -150,6 +150,20 @@ dependencies:
|
|
150
150
|
version: '0'
|
151
151
|
prerelease: false
|
152
152
|
type: :development
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
name: request_store
|
155
|
+
version_requirements: !ruby/object:Gem::Requirement
|
156
|
+
requirements:
|
157
|
+
- - '>='
|
158
|
+
- !ruby/object:Gem::Version
|
159
|
+
version: '0'
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
requirements:
|
162
|
+
- - '>='
|
163
|
+
- !ruby/object:Gem::Version
|
164
|
+
version: '0'
|
165
|
+
prerelease: false
|
166
|
+
type: :development
|
153
167
|
- !ruby/object:Gem::Dependency
|
154
168
|
name: alephant-lookup
|
155
169
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -211,16 +225,27 @@ files:
|
|
211
225
|
- lib/alephant/broker.rb
|
212
226
|
- lib/alephant/broker/app.rb
|
213
227
|
- lib/alephant/broker/app/rack.rb
|
228
|
+
- lib/alephant/broker/call_environment.rb
|
229
|
+
- lib/alephant/broker/errors/invalid_asset_id.rb
|
214
230
|
- lib/alephant/broker/errors/invalid_cache_key.rb
|
215
231
|
- lib/alephant/broker/models/request.rb
|
232
|
+
- lib/alephant/broker/models/request/error_request.rb
|
233
|
+
- lib/alephant/broker/models/request/get_request.rb
|
234
|
+
- lib/alephant/broker/models/request/notfound_request.rb
|
235
|
+
- lib/alephant/broker/models/request/post_request.rb
|
236
|
+
- lib/alephant/broker/models/request/status_request.rb
|
237
|
+
- lib/alephant/broker/models/request_factory.rb
|
216
238
|
- lib/alephant/broker/models/request_handler.rb
|
217
239
|
- lib/alephant/broker/models/response.rb
|
218
240
|
- lib/alephant/broker/models/response/asset_response.rb
|
241
|
+
- lib/alephant/broker/models/response/batch_response.rb
|
219
242
|
- lib/alephant/broker/models/response_factory.rb
|
220
243
|
- lib/alephant/broker/version.rb
|
221
244
|
- spec/asset_response_spec.rb
|
245
|
+
- spec/batch_response_spec.rb
|
246
|
+
- spec/get_request_spec.rb
|
247
|
+
- spec/post_request_spec.rb
|
222
248
|
- spec/rack_spec.rb
|
223
|
-
- spec/request_spec.rb
|
224
249
|
- spec/response_factory_spec.rb
|
225
250
|
- spec/spec_helper.rb
|
226
251
|
homepage: https://github.com/BBC-News/alephant-broker
|
@@ -249,7 +274,10 @@ specification_version: 4
|
|
249
274
|
summary: Brokers requests for alephant components
|
250
275
|
test_files:
|
251
276
|
- spec/asset_response_spec.rb
|
277
|
+
- spec/batch_response_spec.rb
|
278
|
+
- spec/get_request_spec.rb
|
279
|
+
- spec/post_request_spec.rb
|
252
280
|
- spec/rack_spec.rb
|
253
|
-
- spec/request_spec.rb
|
254
281
|
- spec/response_factory_spec.rb
|
255
282
|
- spec/spec_helper.rb
|
283
|
+
has_rdoc:
|
data/spec/request_spec.rb
DELETED
@@ -1,51 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe Alephant::Broker::Request do
|
4
|
-
|
5
|
-
describe "#initialize(path, querystring)" do
|
6
|
-
let(:component_id) { 'foo' }
|
7
|
-
let(:querystring) { 'variant=test' }
|
8
|
-
|
9
|
-
|
10
|
-
it "Sets the component id" do
|
11
|
-
|
12
|
-
instance = Alephant::Broker::Request.new("/component/#{component_id}", '')
|
13
|
-
expect(instance.component_id).to eq(component_id)
|
14
|
-
end
|
15
|
-
|
16
|
-
it "Sets the request type to asset" do
|
17
|
-
|
18
|
-
instance = Alephant::Broker::Request.new("/component/#{component_id}", '')
|
19
|
-
expect(instance.type).to eq(:asset)
|
20
|
-
expect(instance.options).to eq({})
|
21
|
-
end
|
22
|
-
|
23
|
-
it "Sets the request type to asset with parsed options" do
|
24
|
-
instance = Alephant::Broker::Request.new("/component/#{component_id}", querystring)
|
25
|
-
expect(instance.type).to eq(:asset)
|
26
|
-
expect(instance.options).to eq({ :variant => 'test' })
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
it "Sets the request type to status" do
|
31
|
-
instance = Alephant::Broker::Request.new("/status", '')
|
32
|
-
expect(instance.type).to eq(:status)
|
33
|
-
end
|
34
|
-
|
35
|
-
it "Sets the default extension" do
|
36
|
-
instance = Alephant::Broker::Request.new("/component/blah", '')
|
37
|
-
expect(instance.extension).to eq(:html)
|
38
|
-
end
|
39
|
-
|
40
|
-
it "Sets the extension from the path" do
|
41
|
-
instance = Alephant::Broker::Request.new("/component/blah.json", '')
|
42
|
-
expect(instance.extension).to eq(:json)
|
43
|
-
end
|
44
|
-
|
45
|
-
it "Sets the content type to default if the extension does not exist" do
|
46
|
-
instance = Alephant::Broker::Request.new("/component/blah.test", '')
|
47
|
-
expect(instance.content_type).to eq('text/html')
|
48
|
-
end
|
49
|
-
|
50
|
-
end
|
51
|
-
end
|