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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 62ea8a88fdcc92e2e8d8cacf3b7b35e4dc3077d0
4
- data.tar.gz: e58c67bdb11c2b4028bb897337f795ca13e9a48f
3
+ metadata.gz: 88c15819c22cfcde769e9b1b1406d9563ddd11f8
4
+ data.tar.gz: f1ed322acae0dc5740f6a965e3d790e1fca99dfd
5
5
  SHA512:
6
- metadata.gz: f4a00e454e3dd9ea1b6ca4bfd8c62e99df6791891c30873153a1546254e29c679e4145751cb7371f46da59f317c583f5a35231650d954fb863b97d7a6dcbef99
7
- data.tar.gz: 2dbbb0dbdd399039794d5e72f120d1901087506e544384ada28c627422e7e2639dc1eee9b507e68925e06e82d0ffa8fba5b6db05eaa5f3f32f44cd49492bb8e0
6
+ metadata.gz: c3360481c1f7707c893d55635660cf3a5c56894c71aba9d87d80e73c549338ed47b9cede9a36233dbe5f0459b8405d7dbd39824819b4f2d42fcfc06aba0448c8
7
+ data.tar.gz: 2192c4157e16662cf51d26645d9cb0e9c1f859d487669926a87ab68bba3a78046de9eb49cc1cf8fa2dba60db5e579baf7c5e265b8cf2a3a5944119baa5913600
@@ -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"
@@ -4,9 +4,8 @@ require "alephant/broker/models/request_handler"
4
4
  module Alephant
5
5
  module Broker
6
6
 
7
- def self.handle(request, config = {})
8
- @@request_handler ||= RequestHandler.new(config)
9
- @@request_handler.process(request)
7
+ def self.handle(config = {})
8
+ RequestHandler.new(config).process
10
9
  end
11
10
  end
12
11
 
@@ -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(request)
17
- Alephant::Broker.handle(request, @config)
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
- response = handle(
11
- request_from(env['PATH_INFO'], env['QUERY_STRING'])
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
@@ -0,0 +1,11 @@
1
+ module Alephant
2
+ module Broker
3
+ class InvalidAssetId < Exception
4
+
5
+ def initialize(msg)
6
+ super
7
+ end
8
+
9
+ end
10
+ end
11
+ 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(path, querystring)
18
- request = request_components(path, querystring)
19
- case request[:type]
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,11 @@
1
+ require 'alephant/broker/models/request'
2
+
3
+ module Alephant
4
+ module Broker
5
+ class ErrorRequest < Request
6
+ def initialize
7
+ super(:error)
8
+ end
9
+ end
10
+ end
11
+ 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,11 @@
1
+ require 'alephant/broker/models/request'
2
+
3
+ module Alephant
4
+ module Broker
5
+ class NotFoundRequest < Request
6
+ def initialize
7
+ super(:notfound)
8
+ end
9
+ end
10
+ end
11
+ 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,11 @@
1
+ require 'alephant/broker/models/request'
2
+
3
+ module Alephant
4
+ module Broker
5
+ class StatusRequest < Request
6
+ def initialize
7
+ super(:status)
8
+ end
9
+ end
10
+ end
11
+ 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/request'
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(request)
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
@@ -1,5 +1,5 @@
1
1
  module Alephant
2
2
  module Broker
3
- VERSION = "0.0.3"
3
+ VERSION = "0.1.0"
4
4
  end
5
5
  end
@@ -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).to receive(:read).with(request.options).and_return(location)
17
- Alephant::Cache.any_instance.stub(:initialize)
18
- Alephant::Cache.any_instance.stub(:get).with(location).and_return('Test cache content')
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).to receive(:read).with(request.options).and_return(nil)
27
- Alephant::Cache.any_instance.stub(:initialize)
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).to receive(:read).with(request.options).and_raise(Exception)
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
@@ -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 rack app tests' do
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 "Tests status page" do
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 '/component/test_component'
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 '/component/test_component?variant=test_variant'
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 '/component/test_component'
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 '/component/test_component'
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 as asset response" do
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.any_instance.stub(:initialize).with(request, {})
13
- expect(instance.response_from(request)).to be_a Alephant::Broker::AssetResponse
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 a status response" do
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 a 404 response" do
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 a 500 response" do
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
@@ -1,5 +1,5 @@
1
- $: << File.join(File.dirname(__FILE__),"..", "lib")
1
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
2
2
 
3
+ require 'pry'
3
4
  require 'alephant/broker'
4
-
5
-
5
+ require 'request_store'
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.3
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-02-24 00:00:00.000000000 Z
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:
@@ -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