heroics 0.0.14 → 0.0.15
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/.travis.yml +5 -3
- data/heroics.gemspec +1 -1
- data/lib/heroics.rb +1 -0
- data/lib/heroics/cli.rb +1 -0
- data/lib/heroics/client.rb +1 -0
- data/lib/heroics/client_generator.rb +1 -0
- data/lib/heroics/command.rb +1 -0
- data/lib/heroics/errors.rb +1 -0
- data/lib/heroics/link.rb +43 -17
- data/lib/heroics/naming.rb +1 -0
- data/lib/heroics/resource.rb +1 -0
- data/lib/heroics/schema.rb +1 -0
- data/lib/heroics/version.rb +2 -1
- data/lib/heroics/views/client.erb +2 -3
- data/test.rb +1 -0
- data/test/cli_test.rb +1 -0
- data/test/client_generator_test.rb +1 -0
- data/test/client_test.rb +1 -0
- data/test/command_test.rb +1 -0
- data/test/helper.rb +1 -0
- data/test/link_test.rb +46 -0
- data/test/naming_test.rb +1 -0
- data/test/resource_test.rb +1 -0
- data/test/schema_test.rb +1 -0
- data/test/version_test.rb +1 -0
- metadata +5 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5fdba196ca9514256d462ec682debf617bf37f16
|
4
|
+
data.tar.gz: af76b3f90fd215ee446b0c954b35dbf9071c3b2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a73cb1eba0b3ae7f3390612af5b99fdbd323a73838f810c569179bd0d6f25a15f85b500d1d934e37f627de84e802fc5b9c1d6674b3b0c3e81f6bf3bd66fd50e6
|
7
|
+
data.tar.gz: 313d065db244cb6c99c5ccb02ec781188125f5de45c35c77630966d046c3b6443a6e3217c20637fbbebb7b4dd5a6eb5c0279b0c14e9d4987790dc3db2dc013ee
|
data/.travis.yml
CHANGED
data/heroics.gemspec
CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
|
|
25
25
|
spec.add_development_dependency 'rake'
|
26
26
|
spec.add_development_dependency 'turn'
|
27
27
|
|
28
|
-
spec.add_dependency 'erubis', '~> 2.
|
28
|
+
spec.add_dependency 'erubis', '~> 2.0'
|
29
29
|
spec.add_dependency 'excon'
|
30
30
|
spec.add_dependency 'moneta'
|
31
31
|
spec.add_dependency 'multi_json', '>= 1.9.2'
|
data/lib/heroics.rb
CHANGED
data/lib/heroics/cli.rb
CHANGED
data/lib/heroics/client.rb
CHANGED
data/lib/heroics/command.rb
CHANGED
data/lib/heroics/errors.rb
CHANGED
data/lib/heroics/link.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
module Heroics
|
2
3
|
# A link invokes requests with an HTTP server.
|
3
4
|
class Link
|
@@ -50,25 +51,14 @@ module Heroics
|
|
50
51
|
headers = headers.merge({'Content-Type' => @link_schema.content_type})
|
51
52
|
body = @link_schema.encode(body)
|
52
53
|
end
|
53
|
-
cache_key = "#{path}:#{headers.hash}"
|
54
|
-
if @link_schema.method == :get
|
55
|
-
etag = @cache["etag:#{cache_key}"]
|
56
|
-
headers = headers.merge({'If-None-Match' => etag}) if etag
|
57
|
-
end
|
58
54
|
|
59
|
-
connection = Excon.new(@root_url)
|
60
|
-
response = connection
|
55
|
+
connection = Excon.new(@root_url, thread_safe_sockets: true)
|
56
|
+
response = request_with_cache(connection,
|
57
|
+
method: @link_schema.method, path: path,
|
61
58
|
headers: headers, body: body,
|
62
|
-
expects: [200, 201, 202, 204, 206
|
59
|
+
expects: [200, 201, 202, 204, 206])
|
63
60
|
content_type = response.headers['Content-Type']
|
64
|
-
if
|
65
|
-
MultiJson.load(@cache["data:#{cache_key}"])
|
66
|
-
elsif content_type && content_type =~ /application\/.*json/
|
67
|
-
etag = response.headers['ETag']
|
68
|
-
if etag
|
69
|
-
@cache["etag:#{cache_key}"] = etag
|
70
|
-
@cache["data:#{cache_key}"] = response.body
|
71
|
-
end
|
61
|
+
if content_type && content_type =~ /application\/.*json/
|
72
62
|
body = MultiJson.load(response.body)
|
73
63
|
if response.status == 206
|
74
64
|
next_range = response.headers['Next-Range']
|
@@ -83,7 +73,8 @@ module Heroics
|
|
83
73
|
# next range.
|
84
74
|
break unless next_range
|
85
75
|
headers = headers.merge({'Range' => next_range})
|
86
|
-
response = connection
|
76
|
+
response = request_with_cache(connection,
|
77
|
+
method: @link_schema.method,
|
87
78
|
path: path, headers: headers,
|
88
79
|
expects: [200, 201, 206])
|
89
80
|
body = MultiJson.load(response.body)
|
@@ -100,6 +91,31 @@ module Heroics
|
|
100
91
|
|
101
92
|
private
|
102
93
|
|
94
|
+
def request_with_cache(connection, options)
|
95
|
+
options[:expects] << 304
|
96
|
+
cache_key = "#{options[:path]}:#{options[:headers].hash}"
|
97
|
+
if options[:method] == :get
|
98
|
+
etag = @cache["etag:#{cache_key}"]
|
99
|
+
options[:headers] = options[:headers].merge({'If-None-Match' => etag}) if etag
|
100
|
+
end
|
101
|
+
response = connection.request(options)
|
102
|
+
|
103
|
+
if response.status == 304
|
104
|
+
body = @cache["data:#{cache_key}"]
|
105
|
+
status = @cache["status:#{cache_key}"]
|
106
|
+
headers = @cache["headers:#{cache_key}"]
|
107
|
+
CachedResponse.new(status, body, headers)
|
108
|
+
else
|
109
|
+
if etag = response.headers['ETag']
|
110
|
+
@cache["etag:#{cache_key}"] = etag
|
111
|
+
@cache["data:#{cache_key}"] = response.body
|
112
|
+
@cache["status:#{cache_key}"] = response.status
|
113
|
+
@cache["headers:#{cache_key}"] = response.headers
|
114
|
+
end
|
115
|
+
response
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
103
119
|
# Unpack the URL and split it into a root URL and a path prefix, if one
|
104
120
|
# exists.
|
105
121
|
#
|
@@ -116,5 +132,15 @@ module Heroics
|
|
116
132
|
path_prefix = parts[5]
|
117
133
|
return root_url.join(''), path_prefix
|
118
134
|
end
|
135
|
+
|
136
|
+
class CachedResponse
|
137
|
+
attr_reader :status, :body, :headers
|
138
|
+
def initialize(status, body, headers)
|
139
|
+
@status = status
|
140
|
+
@body = body
|
141
|
+
@headers = headers
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
119
145
|
end
|
120
146
|
end
|
data/lib/heroics/naming.rb
CHANGED
data/lib/heroics/resource.rb
CHANGED
data/lib/heroics/schema.rb
CHANGED
data/lib/heroics/version.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
4
|
#
|
4
5
|
# WARNING: Do not edit by hand, this file was generated by Heroics:
|
@@ -66,7 +67,7 @@ module <%= @module_name %>
|
|
66
67
|
final_options[:default_headers].merge!(options[:default_headers])
|
67
68
|
end
|
68
69
|
final_options[:cache] = options[:cache] if options[:cache]
|
69
|
-
final_options[:url] = options[:url]
|
70
|
+
final_options[:url] = options[:url] || <%= @cache %>
|
70
71
|
final_options[:user] = options[:user] if options[:user]
|
71
72
|
final_options
|
72
73
|
end
|
@@ -74,10 +75,8 @@ module <%= @module_name %>
|
|
74
75
|
# Get the default options.
|
75
76
|
def self.default_options
|
76
77
|
default_headers = <%= @default_headers %>
|
77
|
-
cache = <%= @cache %>
|
78
78
|
{
|
79
79
|
default_headers: default_headers,
|
80
|
-
cache: cache,
|
81
80
|
url: "<%= @url %>"
|
82
81
|
}
|
83
82
|
end
|
data/test.rb
CHANGED
data/test/cli_test.rb
CHANGED
data/test/client_test.rb
CHANGED
data/test/command_test.rb
CHANGED
data/test/helper.rb
CHANGED
data/test/link_test.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'helper'
|
2
3
|
|
3
4
|
class LinkTest < MiniTest::Unit::TestCase
|
@@ -339,6 +340,8 @@ class LinkTest < MiniTest::Unit::TestCase
|
|
339
340
|
cache = Moneta.new(:Memory)
|
340
341
|
cache["etag:/resource:#{headers.hash}"] = 'etag-contents'
|
341
342
|
cache["data:/resource:#{headers.hash}"] = MultiJson.dump(body)
|
343
|
+
cache["status:/resource:#{headers.hash}"] = 200
|
344
|
+
cache["headers:/resource:#{headers.hash}"] = {'Content-Type' => 'application/json'}
|
342
345
|
schema = Heroics::Schema.new(SAMPLE_SCHEMA)
|
343
346
|
link = Heroics::Link.new('https://example.com',
|
344
347
|
schema.resource('resource').link('list'),
|
@@ -395,4 +398,47 @@ class LinkTest < MiniTest::Unit::TestCase
|
|
395
398
|
schema.resource('resource').link('list'))
|
396
399
|
assert_equal([1, 2], link.run.to_a)
|
397
400
|
end
|
401
|
+
|
402
|
+
# Ensure that caching does not prevent pagination from working correctly.
|
403
|
+
# See https://github.com/heroku/platform-api/issues/16
|
404
|
+
def test_run_with_range_response_and_cache
|
405
|
+
Excon.stub(method: :get) do |request|
|
406
|
+
Excon.stubs.shift
|
407
|
+
{status: 206, headers: {'Content-Type' => 'application/json',
|
408
|
+
'Content-Range' => 'id 1..2; max=200',
|
409
|
+
'ETag' => 'second-page'},
|
410
|
+
body: MultiJson.dump([2])}
|
411
|
+
end
|
412
|
+
|
413
|
+
Excon.stub(method: :get) do |request|
|
414
|
+
Excon.stubs.shift
|
415
|
+
{status: 206, headers: {'Content-Type' => 'application/json',
|
416
|
+
'Content-Range' => 'id 0..1; max=200',
|
417
|
+
'Next-Range' => '201',
|
418
|
+
'ETag' => 'first-page'},
|
419
|
+
body: MultiJson.dump([1])}
|
420
|
+
end
|
421
|
+
|
422
|
+
schema = Heroics::Schema.new(SAMPLE_SCHEMA)
|
423
|
+
link = Heroics::Link.new('https://example.com',
|
424
|
+
schema.resource('resource').link('list'),
|
425
|
+
cache: Moneta.new(:Memory))
|
426
|
+
assert_equal([1, 2], link.run.to_a)
|
427
|
+
|
428
|
+
Excon.stub(method: :get) do |request|
|
429
|
+
assert_equal('second-page', request[:headers]['If-None-Match'])
|
430
|
+
assert_equal('201', request[:headers]['Range'])
|
431
|
+
Excon.stubs.shift
|
432
|
+
{status: 304, headers: {'Content-Type' => 'application/json'}}
|
433
|
+
end
|
434
|
+
|
435
|
+
Excon.stub(method: :get) do |request|
|
436
|
+
assert_equal('first-page', request[:headers]['If-None-Match'])
|
437
|
+
assert_equal(nil, request[:headers]['Range'])
|
438
|
+
Excon.stubs.shift
|
439
|
+
{status: 304, headers: {'Content-Type' => 'application/json'}}
|
440
|
+
end
|
441
|
+
|
442
|
+
assert_equal([1, 2], link.run.to_a)
|
443
|
+
end
|
398
444
|
end
|
data/test/naming_test.rb
CHANGED
data/test/resource_test.rb
CHANGED
data/test/schema_test.rb
CHANGED
data/test/version_test.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: heroics
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.15
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- geemus
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2016-03-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -73,14 +73,14 @@ dependencies:
|
|
73
73
|
requirements:
|
74
74
|
- - "~>"
|
75
75
|
- !ruby/object:Gem::Version
|
76
|
-
version: 2.
|
76
|
+
version: '2.0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
81
|
- - "~>"
|
82
82
|
- !ruby/object:Gem::Version
|
83
|
-
version: 2.
|
83
|
+
version: '2.0'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: excon
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
@@ -202,7 +202,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
202
202
|
version: '0'
|
203
203
|
requirements: []
|
204
204
|
rubyforge_project:
|
205
|
-
rubygems_version: 2.
|
205
|
+
rubygems_version: 2.5.1
|
206
206
|
signing_key:
|
207
207
|
specification_version: 4
|
208
208
|
summary: A Ruby client generator for HTTP APIs described with a JSON schema
|