alephant-broker 3.10.2 → 3.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/alephant-broker.gemspec +1 -0
- data/lib/alephant/broker/environment.rb +6 -6
- data/lib/alephant/broker/request/batch.rb +22 -9
- data/lib/alephant/broker/request/factory.rb +4 -4
- data/lib/alephant/broker/response/base.rb +2 -1
- data/lib/alephant/broker/version.rb +1 -1
- data/spec/integration/rack_spec.rb +129 -4
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 58251bb948e3620c95b0c67e8643e60426c25818
|
4
|
+
data.tar.gz: c355b17fe2d366043fbd84f5e284377f9d353a44
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dbdaf0f97e7c873b030be8418d6b7b7a076826fcd576d7f60b9c5f734f4ac8a13db6af1cb4744b222b48ee01abd267c6df051f22fac85dd8285b53b36128ce2c
|
7
|
+
data.tar.gz: a143fb0fbca1a39ab62a1a7facd718f9f38221a53daae7514ca82d1f9b7a42b3992ba06f8b427da717a919a50801f9877bb56d7c4b34e7adeae69702c5d63fde
|
data/alephant-broker.gemspec
CHANGED
@@ -13,23 +13,23 @@ module Alephant
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def method
|
16
|
-
settings[
|
16
|
+
settings["REQUEST_METHOD"]
|
17
17
|
end
|
18
18
|
|
19
19
|
def post?
|
20
|
-
settings[
|
20
|
+
settings["REQUEST_METHOD"] == "POST"
|
21
21
|
end
|
22
22
|
|
23
23
|
def get?
|
24
|
-
settings[
|
24
|
+
settings["REQUEST_METHOD"] == "GET"
|
25
25
|
end
|
26
26
|
|
27
27
|
def query
|
28
|
-
settings[
|
28
|
+
settings["QUERY_STRING"] || ""
|
29
29
|
end
|
30
30
|
|
31
31
|
def path
|
32
|
-
settings[
|
32
|
+
settings["PATH_INFO"]
|
33
33
|
end
|
34
34
|
|
35
35
|
def if_none_match
|
@@ -51,7 +51,7 @@ module Alephant
|
|
51
51
|
private
|
52
52
|
|
53
53
|
def rack_input
|
54
|
-
(settings[
|
54
|
+
(settings["rack.input"].read).tap { settings["rack.input"].rewind }
|
55
55
|
end
|
56
56
|
|
57
57
|
def parse(json)
|
@@ -10,24 +10,37 @@ module Alephant
|
|
10
10
|
attr_reader :batch_id, :components, :load_strategy
|
11
11
|
|
12
12
|
def initialize(component_factory, env)
|
13
|
-
|
13
|
+
if env.data
|
14
|
+
@batch_id = env.data["batch_id"]
|
15
|
+
else
|
16
|
+
@batch_id = env.options.fetch("batch_id", nil)
|
17
|
+
end
|
18
|
+
|
19
|
+
logger.info "Request::Batch#initialize: id: #{batch_id}"
|
14
20
|
|
15
|
-
@batch_id = env.data["batch_id"] if env.data
|
16
21
|
@component_factory = component_factory
|
17
|
-
|
22
|
+
|
23
|
+
@components = env.post? ? components_post(env) : components_get(env)
|
18
24
|
end
|
19
25
|
|
20
26
|
private
|
21
27
|
|
22
|
-
def
|
28
|
+
def components_post(env)
|
23
29
|
((env.data || {}).fetch("components", []) || []).map do |c|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
create_component(c["component"], batch_id, c["options"])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def components_get(env)
|
35
|
+
(env.options.fetch("components", []) || []).map do |c|
|
36
|
+
options = c[1].fetch("options", {}) || {}
|
37
|
+
create_component(c[1]["component"], batch_id, options)
|
29
38
|
end
|
30
39
|
end
|
40
|
+
|
41
|
+
def create_component(component, batch_id, options)
|
42
|
+
@component_factory.create(component, batch_id, options)
|
43
|
+
end
|
31
44
|
end
|
32
45
|
end
|
33
46
|
end
|
@@ -6,18 +6,18 @@ module Alephant
|
|
6
6
|
module Request
|
7
7
|
class Factory
|
8
8
|
def self.request_type_from(env)
|
9
|
-
env.path.split(
|
9
|
+
env.path.split("/")[1]
|
10
10
|
end
|
11
11
|
|
12
12
|
def self.request_for(load_strategy, env)
|
13
13
|
component_factory = ComponentFactory.new load_strategy
|
14
14
|
|
15
15
|
case request_type_from(env)
|
16
|
-
when
|
16
|
+
when "component"
|
17
17
|
Asset.new(component_factory, env)
|
18
|
-
when
|
18
|
+
when "components"
|
19
19
|
Batch.new(component_factory, env)
|
20
|
-
when
|
20
|
+
when "status"
|
21
21
|
Status.new
|
22
22
|
else
|
23
23
|
NotFound.new
|
@@ -12,7 +12,7 @@ module Alephant
|
|
12
12
|
|
13
13
|
attr_reader :content, :headers, :status
|
14
14
|
|
15
|
-
NOT_MODIFIED_STATUS_CODE =
|
15
|
+
NOT_MODIFIED_STATUS_CODE = 304
|
16
16
|
|
17
17
|
STATUS_CODE_MAPPING = {
|
18
18
|
200 => "ok",
|
@@ -62,6 +62,7 @@ module Alephant
|
|
62
62
|
end
|
63
63
|
|
64
64
|
def self.component_not_modified(headers, request_env)
|
65
|
+
return false if request_env.post?
|
65
66
|
return false if request_env.if_modified_since.nil? && request_env.if_none_match.nil?
|
66
67
|
|
67
68
|
last_modified_match = !request_env.if_modified_since.nil? && headers["Last-Modified"] == request_env.if_modified_since
|
@@ -117,7 +117,7 @@ describe Alephant::Broker::Application do
|
|
117
117
|
specify { expect(last_response.headers["Last-Modified"]).to eq("Mon, 11 Apr 2016 10:39:57 GMT") }
|
118
118
|
end
|
119
119
|
|
120
|
-
describe "Components endpoint '/components'" do
|
120
|
+
describe "Components endpoint '/components' POST" do
|
121
121
|
let(:fixture_path) { "#{File.dirname(__FILE__)}/../fixtures/json" }
|
122
122
|
let(:batch_json) do
|
123
123
|
IO.read("#{fixture_path}/batch.json").strip
|
@@ -169,7 +169,7 @@ describe Alephant::Broker::Application do
|
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
172
|
-
describe "Components unmodified '/components' response" do
|
172
|
+
describe "Components POST unmodified '/components' response" do
|
173
173
|
let(:fixture_path) { "#{File.dirname(__FILE__)}/../fixtures/json" }
|
174
174
|
let(:batch_json) { IO.read("#{fixture_path}/batch.json").strip }
|
175
175
|
let(:batch_compiled_json) { IO.read("#{fixture_path}/batch_compiled.json").strip }
|
@@ -216,8 +216,8 @@ describe Alephant::Broker::Application do
|
|
216
216
|
"HTTP_IF_NONE_MATCH" => etag)
|
217
217
|
end
|
218
218
|
|
219
|
-
specify { expect(last_response.status).to eql
|
220
|
-
specify { expect(last_response.body).to eq
|
219
|
+
specify { expect(last_response.status).to eql 200 }
|
220
|
+
specify { expect(last_response.body).to eq batch_compiled_json }
|
221
221
|
|
222
222
|
describe "response should have headers" do
|
223
223
|
it "should have a Content-Type header" do
|
@@ -241,6 +241,131 @@ describe Alephant::Broker::Application do
|
|
241
241
|
end
|
242
242
|
end
|
243
243
|
|
244
|
+
describe "Components endpoint '/components' GET" do
|
245
|
+
let(:fixture_path) { "#{File.dirname(__FILE__)}/../fixtures/json" }
|
246
|
+
let(:batch_compiled_json) do
|
247
|
+
IO.read("#{fixture_path}/batch_compiled.json").strip
|
248
|
+
end
|
249
|
+
let(:s3_double_batch) { instance_double("Alephant::Storage") }
|
250
|
+
|
251
|
+
before do
|
252
|
+
allow(s3_double_batch).to receive(:get).and_return(
|
253
|
+
content,
|
254
|
+
AWS::Core::Data.new(
|
255
|
+
:content_type => "test/content",
|
256
|
+
:content => "Test",
|
257
|
+
:meta => {
|
258
|
+
:head_ETag => "\"abc\"",
|
259
|
+
:"head_Last-Modified" => "Mon, 11 Apr 2016 09:39:57 GMT"
|
260
|
+
}
|
261
|
+
)
|
262
|
+
)
|
263
|
+
|
264
|
+
allow(Alephant::Storage).to receive(:new) { s3_double_batch }
|
265
|
+
end
|
266
|
+
|
267
|
+
context "when using valid batch asset data" do
|
268
|
+
let(:path) { "/components/batch?batch_id=baz&components[ni_council_results_table][component]=ni_council_results_table&components[ni_council_results_table][options][foo]=bar&components[ni_council_results_table_no_options][component]=ni_council_results_table" }
|
269
|
+
let(:content_type) { "application/json" }
|
270
|
+
|
271
|
+
before { get path, {}, "CONTENT_TYPE" => content_type }
|
272
|
+
|
273
|
+
specify { expect(last_response.status).to eql 200 }
|
274
|
+
specify { expect(last_response.body).to eq batch_compiled_json }
|
275
|
+
|
276
|
+
describe "response should have headers" do
|
277
|
+
it "should have content headers" do
|
278
|
+
expect(last_response.headers["Content-Type"]).to eq("application/json")
|
279
|
+
expect(last_response.headers["Content-Length"]).to eq("266")
|
280
|
+
end
|
281
|
+
|
282
|
+
it "should have ETag cache header" do
|
283
|
+
expect(last_response.headers["ETag"]).to eq('"34774567db979628363e6e865127623f"')
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should have most recent Last-Modified header" do
|
287
|
+
expect(last_response.headers["Last-Modified"]).to eq("Mon, 11 Apr 2016 10:39:57 GMT")
|
288
|
+
end
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
describe "Components GET unmodified '/components' response" do
|
294
|
+
let(:fixture_path) { "#{File.dirname(__FILE__)}/../fixtures/json" }
|
295
|
+
let(:batch_compiled_json) { IO.read("#{fixture_path}/batch_compiled.json").strip }
|
296
|
+
let(:s3_double_with_etag) { instance_double("Alephant::Storage") }
|
297
|
+
let(:lookup_location_double_for_options_request) do
|
298
|
+
instance_double("Alephant::Lookup::Location", :location => "test/location/with/options")
|
299
|
+
end
|
300
|
+
|
301
|
+
before do
|
302
|
+
allow(lookup_helper_double).to receive(:read)
|
303
|
+
.with("ni_council_results_table", { :foo => "bar" }, "111")
|
304
|
+
.and_return(lookup_location_double_for_options_request)
|
305
|
+
|
306
|
+
allow(s3_double_with_etag).to receive(:get)
|
307
|
+
.with("test/location")
|
308
|
+
.and_return(
|
309
|
+
content
|
310
|
+
)
|
311
|
+
|
312
|
+
allow(s3_double_with_etag).to receive(:get)
|
313
|
+
.with("test/location/with/options")
|
314
|
+
.and_return(
|
315
|
+
AWS::Core::Data.new(
|
316
|
+
:content_type => "test/content",
|
317
|
+
:content => "Test",
|
318
|
+
:meta => {
|
319
|
+
"head_ETag" => "abc",
|
320
|
+
"head_Last-Modified" => "Mon, 11 Apr 2016 09:39:57 GMT"
|
321
|
+
}
|
322
|
+
)
|
323
|
+
)
|
324
|
+
|
325
|
+
allow(Alephant::Storage).to receive(:new) { s3_double_with_etag }
|
326
|
+
end
|
327
|
+
|
328
|
+
context "when requesting an unmodified response with GET" do
|
329
|
+
let(:path) { "/components/batch?batch_id=baz&components[ni_council_results_table][component]=ni_council_results_table&components[ni_council_results_table][options][foo]=bar&components[ni_council_results_table_no_options][component]=ni_council_results_table" }
|
330
|
+
let(:content_type) { "application/json" }
|
331
|
+
let(:etag) { '"34774567db979628363e6e865127623f"' }
|
332
|
+
|
333
|
+
before do
|
334
|
+
get(
|
335
|
+
path,
|
336
|
+
{},
|
337
|
+
{
|
338
|
+
"CONTENT_TYPE" => content_type,
|
339
|
+
"HTTP_IF_NONE_MATCH" => etag
|
340
|
+
}
|
341
|
+
)
|
342
|
+
end
|
343
|
+
|
344
|
+
specify { expect(last_response.status).to eql not_modified_status_code }
|
345
|
+
specify { expect(last_response.body).to eq "" }
|
346
|
+
|
347
|
+
describe "response should have headers" do
|
348
|
+
it "should not have a Content-Type header" do
|
349
|
+
expect(last_response.headers).to_not include("Content-Type")
|
350
|
+
end
|
351
|
+
|
352
|
+
it "should have ETag cache header" do
|
353
|
+
expect(last_response.headers["ETag"]).to eq(etag)
|
354
|
+
end
|
355
|
+
|
356
|
+
it "should have most recent Last-Modified header" do
|
357
|
+
expect(last_response.headers["Last-Modified"]).to eq("Mon, 11 Apr 2016 10:39:57 GMT")
|
358
|
+
end
|
359
|
+
|
360
|
+
it "shoud not have no cache headers" do
|
361
|
+
expect(last_response.headers).to_not include("Cache-Control")
|
362
|
+
expect(last_response.headers).to_not include("Pragma")
|
363
|
+
expect(last_response.headers).to_not include("Expires")
|
364
|
+
end
|
365
|
+
end
|
366
|
+
end
|
367
|
+
end
|
368
|
+
|
244
369
|
describe "S3 headers" do
|
245
370
|
let(:content) do
|
246
371
|
AWS::Core::Data.new(
|
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: 3.
|
4
|
+
version: 3.11.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BBC News
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-04-
|
11
|
+
date: 2016-04-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
requirement: !ruby/object:Gem::Requirement
|
@@ -262,6 +262,20 @@ dependencies:
|
|
262
262
|
- - '>='
|
263
263
|
- !ruby/object:Gem::Version
|
264
264
|
version: '0'
|
265
|
+
- !ruby/object:Gem::Dependency
|
266
|
+
requirement: !ruby/object:Gem::Requirement
|
267
|
+
requirements:
|
268
|
+
- - ~>
|
269
|
+
- !ruby/object:Gem::Version
|
270
|
+
version: 3.0.0
|
271
|
+
name: listen
|
272
|
+
prerelease: false
|
273
|
+
type: :runtime
|
274
|
+
version_requirements: !ruby/object:Gem::Requirement
|
275
|
+
requirements:
|
276
|
+
- - ~>
|
277
|
+
- !ruby/object:Gem::Version
|
278
|
+
version: 3.0.0
|
265
279
|
description: Brokers requests for alephant components
|
266
280
|
email:
|
267
281
|
- FutureMediaNewsRubyGems@bbc.co.uk
|