restify 1.15.2 → 2.0.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/CHANGELOG.md +25 -2
- data/README.md +23 -31
- data/lib/restify/adapter/base.rb +4 -0
- data/lib/restify/adapter/telemetry.rb +54 -0
- data/lib/restify/adapter/typhoeus.rb +21 -3
- data/lib/restify/context.rb +3 -3
- data/lib/restify/error.rb +2 -2
- data/lib/restify/link.rb +4 -4
- data/lib/restify/processors/base/parsing.rb +2 -21
- data/lib/restify/processors/base.rb +1 -1
- data/lib/restify/promise.rb +2 -2
- data/lib/restify/registry.rb +1 -1
- data/lib/restify/relation.rb +45 -17
- data/lib/restify/request.rb +6 -6
- data/lib/restify/timeout.rb +2 -2
- data/lib/restify/version.rb +3 -3
- data/lib/restify.rb +0 -1
- data/spec/restify/cache_spec.rb +16 -12
- data/spec/restify/context_spec.rb +8 -3
- data/spec/restify/error_spec.rb +13 -16
- data/spec/restify/features/head_requests_spec.rb +5 -4
- data/spec/restify/features/request_bodies_spec.rb +8 -8
- data/spec/restify/features/request_errors_spec.rb +2 -2
- data/spec/restify/features/request_headers_spec.rb +3 -6
- data/spec/restify/features/response_errors_spec.rb +1 -1
- data/spec/restify/global_spec.rb +10 -10
- data/spec/restify/processors/base_spec.rb +6 -7
- data/spec/restify/processors/json_spec.rb +21 -62
- data/spec/restify/processors/msgpack_spec.rb +33 -70
- data/spec/restify/promise_spec.rb +31 -31
- data/spec/restify/registry_spec.rb +5 -7
- data/spec/restify/relation_spec.rb +185 -7
- data/spec/restify/resource_spec.rb +47 -53
- data/spec/restify/timeout_spec.rb +3 -3
- data/spec/restify_spec.rb +12 -73
- data/spec/spec_helper.rb +11 -15
- metadata +33 -64
- data/lib/restify/adapter/em.rb +0 -134
- data/lib/restify/adapter/pooled_em.rb +0 -269
data/spec/restify/error_spec.rb
CHANGED
@@ -2,16 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Restify::ResponseError do
|
6
|
-
let(:response) {
|
5
|
+
describe Restify::ResponseError do # rubocop:disable RSpec/SpecFilePathFormat
|
6
|
+
let(:response) { instance_double(Restify::Response) }
|
7
7
|
let(:message) { 'Error' }
|
8
8
|
let(:uri) { 'http://localhost' }
|
9
9
|
|
10
10
|
before do
|
11
|
-
allow(response).to
|
12
|
-
allow(response).to receive(:code).and_return(code)
|
13
|
-
allow(response).to receive(:message).and_return(message)
|
14
|
-
allow(response).to receive(:decoded_body).and_return({})
|
11
|
+
allow(response).to receive_messages(uri: uri, code: code, message: message, decoded_body: {})
|
15
12
|
end
|
16
13
|
|
17
14
|
describe '.from_code' do
|
@@ -20,61 +17,61 @@ describe Restify::ResponseError do
|
|
20
17
|
context 'with 400 Bad Request' do
|
21
18
|
let(:code) { 400 }
|
22
19
|
|
23
|
-
it { is_expected.to be_a
|
20
|
+
it { is_expected.to be_a Restify::BadRequest }
|
24
21
|
end
|
25
22
|
|
26
23
|
context 'with 401 Unauthorized' do
|
27
24
|
let(:code) { 401 }
|
28
25
|
|
29
|
-
it { is_expected.to be_a
|
26
|
+
it { is_expected.to be_a Restify::Unauthorized }
|
30
27
|
end
|
31
28
|
|
32
29
|
context 'with 404 Unauthorized' do
|
33
30
|
let(:code) { 404 }
|
34
31
|
|
35
|
-
it { is_expected.to be_a
|
32
|
+
it { is_expected.to be_a Restify::NotFound }
|
36
33
|
end
|
37
34
|
|
38
35
|
context 'with 406 Not Acceptable' do
|
39
36
|
let(:code) { 406 }
|
40
37
|
|
41
|
-
it { is_expected.to be_a
|
38
|
+
it { is_expected.to be_a Restify::NotAcceptable }
|
42
39
|
end
|
43
40
|
|
44
41
|
context 'with 410 Gone' do
|
45
42
|
let(:code) { 410 }
|
46
43
|
|
47
|
-
it { is_expected.to be_a
|
44
|
+
it { is_expected.to be_a Restify::Gone }
|
48
45
|
end
|
49
46
|
|
50
47
|
context 'with 422 Unprocessable Entity' do
|
51
48
|
let(:code) { 422 }
|
52
49
|
|
53
|
-
it { is_expected.to be_a
|
50
|
+
it { is_expected.to be_a Restify::UnprocessableEntity }
|
54
51
|
end
|
55
52
|
|
56
53
|
context 'with 500 Internal Server Error' do
|
57
54
|
let(:code) { 500 }
|
58
55
|
|
59
|
-
it { is_expected.to be_a
|
56
|
+
it { is_expected.to be_a Restify::InternalServerError }
|
60
57
|
end
|
61
58
|
|
62
59
|
context 'with 502 Bad Gateway' do
|
63
60
|
let(:code) { 502 }
|
64
61
|
|
65
|
-
it { is_expected.to be_a
|
62
|
+
it { is_expected.to be_a Restify::BadGateway }
|
66
63
|
end
|
67
64
|
|
68
65
|
context 'with 503 Service Unavailable' do
|
69
66
|
let(:code) { 503 }
|
70
67
|
|
71
|
-
it { is_expected.to be_a
|
68
|
+
it { is_expected.to be_a Restify::ServiceUnavailable }
|
72
69
|
end
|
73
70
|
|
74
71
|
context 'with 504 Gateway Timeout' do
|
75
72
|
let(:code) { 504 }
|
76
73
|
|
77
|
-
it { is_expected.to be_a
|
74
|
+
it { is_expected.to be_a Restify::GatewayTimeout }
|
78
75
|
end
|
79
76
|
end
|
80
77
|
end
|
@@ -16,23 +16,24 @@ describe Restify do
|
|
16
16
|
end
|
17
17
|
|
18
18
|
describe 'HEAD requests' do
|
19
|
-
subject { Restify.new('http://localhost:9292/base').head(params).value! }
|
19
|
+
subject(:value) { Restify.new('http://localhost:9292/base').head(params:).value! }
|
20
20
|
|
21
21
|
let(:params) { {} }
|
22
22
|
|
23
23
|
it 'returns a resource with access to headers' do
|
24
|
-
expect(
|
24
|
+
expect(value.response.headers).to include('CONTENT_LENGTH' => '333')
|
25
25
|
end
|
26
26
|
|
27
27
|
it 'parses Link headers into relations' do
|
28
|
-
expect(
|
28
|
+
expect(value).to have_relation :neat
|
29
29
|
end
|
30
30
|
|
31
31
|
context 'with params' do
|
32
32
|
let(:params) { {foo: 'bar'} }
|
33
33
|
|
34
34
|
it 'adds them to the query string' do
|
35
|
-
|
35
|
+
value
|
36
|
+
|
36
37
|
expect(
|
37
38
|
request_stub.with(query: {foo: 'bar'}),
|
38
39
|
).to have_been_requested
|
@@ -13,7 +13,7 @@ describe Restify do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
describe 'Request body' do
|
16
|
-
subject { Restify.new('http://localhost:9292/base').post(body,
|
16
|
+
subject(:value) { Restify.new('http://localhost:9292/base').post(body, headers:).value! }
|
17
17
|
|
18
18
|
let(:headers) { {} }
|
19
19
|
|
@@ -21,7 +21,7 @@ describe Restify do
|
|
21
21
|
let(:body) { {a: 'b', c: 'd'} }
|
22
22
|
|
23
23
|
it 'is serialized as JSON' do
|
24
|
-
|
24
|
+
value
|
25
25
|
|
26
26
|
expect(
|
27
27
|
request_stub.with(body: '{"a":"b","c":"d"}'),
|
@@ -29,7 +29,7 @@ describe Restify do
|
|
29
29
|
end
|
30
30
|
|
31
31
|
it 'gets a JSON media type for free' do
|
32
|
-
|
32
|
+
value
|
33
33
|
|
34
34
|
expect(
|
35
35
|
request_stub.with(headers: {'Content-Type' => 'application/json'}),
|
@@ -40,7 +40,7 @@ describe Restify do
|
|
40
40
|
let(:headers) { {'Content-Type' => 'application/vnd.api+json'} }
|
41
41
|
|
42
42
|
it 'respects the override' do
|
43
|
-
|
43
|
+
value
|
44
44
|
|
45
45
|
expect(
|
46
46
|
request_stub.with(headers: {'Content-Type' => 'application/vnd.api+json'}),
|
@@ -53,7 +53,7 @@ describe Restify do
|
|
53
53
|
let(:body) { 'a=b&c=d' }
|
54
54
|
|
55
55
|
it 'is sent as provided' do
|
56
|
-
|
56
|
+
value
|
57
57
|
|
58
58
|
expect(
|
59
59
|
request_stub.with(body: 'a=b&c=d'),
|
@@ -61,10 +61,10 @@ describe Restify do
|
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'does not get a JSON media type' do
|
64
|
-
|
64
|
+
value
|
65
65
|
|
66
66
|
expect(
|
67
|
-
request_stub.with {|req| req.headers['Content-Type']
|
67
|
+
request_stub.with {|req| !req.headers['Content-Type'].include?('json') },
|
68
68
|
).to have_been_requested
|
69
69
|
end
|
70
70
|
|
@@ -72,7 +72,7 @@ describe Restify do
|
|
72
72
|
let(:headers) { {'Content-Type' => 'application/text'} }
|
73
73
|
|
74
74
|
it 'respects the override' do
|
75
|
-
|
75
|
+
value
|
76
76
|
|
77
77
|
expect(
|
78
78
|
request_stub.with(headers: {'Content-Type' => 'application/text'}),
|
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
|
-
describe Restify, adapter:
|
5
|
+
describe Restify, adapter: 'Restify::Adapter::Typhoeus' do
|
6
6
|
before do
|
7
7
|
stub_request(:get, 'http://stubserver/base').to_timeout
|
8
8
|
end
|
9
9
|
|
10
10
|
describe 'Timeout' do
|
11
|
-
subject(:request) { Restify.new('http://localhost:9292/base').get(
|
11
|
+
subject(:request) { Restify.new('http://localhost:9292/base').get(timeout: 0.1).value! }
|
12
12
|
|
13
13
|
it 'throws a network error' do
|
14
14
|
expect { request }.to raise_error Restify::NetworkError do |error|
|
@@ -20,8 +20,7 @@ describe Restify do
|
|
20
20
|
|
21
21
|
it 'sends the headers only for that request' do
|
22
22
|
root = context.get(
|
23
|
-
{},
|
24
|
-
{headers: {'Accept' => 'application/msgpack, application/json'}},
|
23
|
+
headers: {'Accept' => 'application/msgpack, application/json'},
|
25
24
|
).value!
|
26
25
|
|
27
26
|
root.rel(:self).get.value!
|
@@ -53,8 +52,7 @@ describe Restify do
|
|
53
52
|
|
54
53
|
it 'can overwrite headers for single requests' do
|
55
54
|
root = context.get(
|
56
|
-
{},
|
57
|
-
{headers: {'Accept' => 'application/xml'}},
|
55
|
+
headers: {'Accept' => 'application/xml'},
|
58
56
|
).value!
|
59
57
|
|
60
58
|
root.rel(:self).get.value!
|
@@ -69,8 +67,7 @@ describe Restify do
|
|
69
67
|
|
70
68
|
it 'can add additional headers for single requests' do
|
71
69
|
root = context.get(
|
72
|
-
{},
|
73
|
-
{headers: {'X-Custom' => 'foobar'}},
|
70
|
+
headers: {'X-Custom' => 'foobar'},
|
74
71
|
).value!
|
75
72
|
|
76
73
|
root.rel(:self).get.value!
|
data/spec/restify/global_spec.rb
CHANGED
@@ -7,21 +7,21 @@ describe Restify::Global do
|
|
7
7
|
|
8
8
|
describe '#new' do
|
9
9
|
context 'with string URI' do
|
10
|
-
subject { global.new
|
10
|
+
subject(:restify) { global.new(uri, **options) }
|
11
11
|
|
12
12
|
let(:uri) { 'http://api.github.com/' }
|
13
13
|
let(:options) { {accept: 'application.vnd.github.v3+json'} }
|
14
14
|
|
15
15
|
it 'returns relation for URI' do
|
16
|
-
expect(
|
17
|
-
expect(
|
18
|
-
expect(
|
19
|
-
expect(
|
16
|
+
expect(restify).to be_a Restify::Relation
|
17
|
+
expect(restify.pattern).to eq uri
|
18
|
+
expect(restify.context.uri.to_s).to eq uri
|
19
|
+
expect(restify.context.options).to eq options
|
20
20
|
end
|
21
21
|
end
|
22
22
|
|
23
23
|
context 'with registry symbol' do
|
24
|
-
subject { global.new(
|
24
|
+
subject(:restify) { global.new(uri, **options) }
|
25
25
|
|
26
26
|
let(:name) { :registry_item_name }
|
27
27
|
let(:uri) { 'http://api.github.com/' }
|
@@ -31,10 +31,10 @@ describe Restify::Global do
|
|
31
31
|
it 'returns relation for stored registry item' do
|
32
32
|
Restify::Registry.store(name, uri, **options)
|
33
33
|
|
34
|
-
expect(
|
35
|
-
expect(
|
36
|
-
expect(
|
37
|
-
expect(
|
34
|
+
expect(restify).to be_a Restify::Relation
|
35
|
+
expect(restify.pattern).to eq uri
|
36
|
+
expect(restify.context.uri.to_s).to eq uri
|
37
|
+
expect(restify.context.options).to eq options
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -4,27 +4,26 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Restify::Processors::Base do
|
6
6
|
let(:context) { Restify::Context.new('http://test.host/') }
|
7
|
-
let(:response) {
|
7
|
+
let(:response) { instance_double(Restify::Response) }
|
8
8
|
|
9
9
|
before do
|
10
|
-
allow(response).to
|
11
|
-
allow(response).to receive(:follow_location).and_return nil
|
10
|
+
allow(response).to receive_messages(links: [], follow_location: nil)
|
12
11
|
end
|
13
12
|
|
14
13
|
describe 'class' do
|
15
14
|
describe '#accept?' do
|
16
|
-
subject { described_class.accept?
|
15
|
+
subject(:accept) { described_class.accept?(response) }
|
17
16
|
|
18
17
|
# If no other processor accepts the request, we have an explicit fallback
|
19
18
|
# to the base processor.
|
20
19
|
it 'does not accept any responses' do
|
21
|
-
expect(
|
20
|
+
expect(accept).to be_falsey
|
22
21
|
end
|
23
22
|
end
|
24
23
|
end
|
25
24
|
|
26
25
|
describe '#resource' do
|
27
|
-
subject { described_class.new(context, response).resource }
|
26
|
+
subject(:resource) { described_class.new(context, response).resource }
|
28
27
|
|
29
28
|
before { allow(response).to receive(:body).and_return(body) }
|
30
29
|
|
@@ -37,7 +36,7 @@ describe Restify::Processors::Base do
|
|
37
36
|
end
|
38
37
|
|
39
38
|
it { is_expected.to be_a Restify::Resource }
|
40
|
-
it { expect(
|
39
|
+
it { expect(resource.response).to be response }
|
41
40
|
it { is_expected.to eq body }
|
42
41
|
end
|
43
42
|
end
|
@@ -4,31 +4,30 @@ require 'spec_helper'
|
|
4
4
|
|
5
5
|
describe Restify::Processors::Json do
|
6
6
|
let(:context) { Restify::Context.new('http://test.host/') }
|
7
|
-
let(:response) {
|
7
|
+
let(:response) { instance_double(Restify::Response) }
|
8
8
|
|
9
9
|
before do
|
10
|
-
allow(response).to
|
11
|
-
allow(response).to receive(:follow_location).and_return nil
|
10
|
+
allow(response).to receive_messages(links: [], follow_location: nil)
|
12
11
|
end
|
13
12
|
|
14
13
|
describe 'class' do
|
15
14
|
describe '#accept?' do
|
16
|
-
subject { described_class.accept?
|
15
|
+
subject(:accept) { described_class.accept?(response) }
|
17
16
|
|
18
17
|
it 'accepts JSON mime type (I)' do
|
19
|
-
|
20
|
-
expect(
|
18
|
+
allow(response).to receive(:content_type).and_return('application/json')
|
19
|
+
expect(accept).to be_truthy
|
21
20
|
end
|
22
21
|
|
23
22
|
it 'accepts JSON mime type (II)' do
|
24
|
-
|
25
|
-
expect(
|
23
|
+
allow(response).to receive(:content_type).and_return('application/json; abc')
|
24
|
+
expect(accept).to be_truthy
|
26
25
|
end
|
27
26
|
end
|
28
27
|
end
|
29
28
|
|
30
29
|
describe '#resource' do
|
31
|
-
subject { described_class.new(context, response).resource }
|
30
|
+
subject(:resource) { described_class.new(context, response).resource }
|
32
31
|
|
33
32
|
before { allow(response).to receive(:body).and_return(body) }
|
34
33
|
|
@@ -41,7 +40,7 @@ describe Restify::Processors::Json do
|
|
41
40
|
end
|
42
41
|
|
43
42
|
it { is_expected.to be_a Restify::Resource }
|
44
|
-
it { expect(
|
43
|
+
it { expect(resource.response).to be response }
|
45
44
|
it { is_expected.to eq 'json' => 'value' }
|
46
45
|
end
|
47
46
|
|
@@ -53,12 +52,12 @@ describe Restify::Processors::Json do
|
|
53
52
|
end
|
54
53
|
|
55
54
|
it do
|
56
|
-
expect(
|
55
|
+
expect(resource).to eq \
|
57
56
|
'json' => 'value', 'search_url' => 'https://google.com{?q}'
|
58
57
|
end
|
59
58
|
|
60
59
|
it { is_expected.to have_relation :search }
|
61
|
-
it { expect(
|
60
|
+
it { expect(resource.relation(:search)).to eq 'https://google.com{?q}' }
|
62
61
|
end
|
63
62
|
|
64
63
|
context 'object with implicit self relation' do
|
@@ -68,7 +67,7 @@ describe Restify::Processors::Json do
|
|
68
67
|
JSON
|
69
68
|
end
|
70
69
|
|
71
|
-
it { expect(
|
70
|
+
it { expect(resource.relation(:self)).to eq '/self' }
|
72
71
|
end
|
73
72
|
|
74
73
|
context 'single array' do
|
@@ -79,7 +78,7 @@ describe Restify::Processors::Json do
|
|
79
78
|
end
|
80
79
|
|
81
80
|
it { is_expected.to be_a Restify::Resource }
|
82
|
-
it { expect(
|
81
|
+
it { expect(resource.response).to be response }
|
83
82
|
it { is_expected.to eq [1, 2, nil, 'STR'] }
|
84
83
|
end
|
85
84
|
|
@@ -102,11 +101,11 @@ describe Restify::Processors::Json do
|
|
102
101
|
end
|
103
102
|
|
104
103
|
it 'parses objects as resources' do
|
105
|
-
expect(
|
104
|
+
expect(resource).to all(be_a(Restify::Resource))
|
106
105
|
end
|
107
106
|
|
108
107
|
it 'parses relations of resources' do
|
109
|
-
expect(
|
108
|
+
expect(resource.map {|r| r.relation :self }).to eq \
|
110
109
|
['/users/john', '/users/jane']
|
111
110
|
end
|
112
111
|
end
|
@@ -120,14 +119,14 @@ describe Restify::Processors::Json do
|
|
120
119
|
end
|
121
120
|
|
122
121
|
it { is_expected.to be_a Restify::Resource }
|
123
|
-
it { expect(
|
122
|
+
it { expect(resource.response).to be response }
|
124
123
|
|
125
124
|
it 'parses objects as resources' do
|
126
|
-
expect(
|
127
|
-
expect(
|
125
|
+
expect(resource['john']).to be_a Restify::Resource
|
126
|
+
expect(resource['jane']).to be_a Restify::Resource
|
128
127
|
|
129
|
-
expect(
|
130
|
-
expect(
|
128
|
+
expect(resource['john']['name']).to eq 'John'
|
129
|
+
expect(resource['jane']['name']).to eq 'Jane'
|
131
130
|
end
|
132
131
|
end
|
133
132
|
|
@@ -139,49 +138,9 @@ describe Restify::Processors::Json do
|
|
139
138
|
end
|
140
139
|
|
141
140
|
it { is_expected.to be_a Restify::Resource }
|
142
|
-
it { expect(
|
141
|
+
it { expect(resource.response).to be response }
|
143
142
|
it { is_expected.to eq 'BLUB' }
|
144
143
|
end
|
145
|
-
|
146
|
-
context 'with indifferent access' do
|
147
|
-
let(:body) do
|
148
|
-
<<-JSON
|
149
|
-
{"name": "John", "age": 24}
|
150
|
-
JSON
|
151
|
-
end
|
152
|
-
|
153
|
-
it '#key?' do
|
154
|
-
expect(subject).to have_key 'name'
|
155
|
-
expect(subject).to have_key 'age'
|
156
|
-
|
157
|
-
expect(subject).to have_key :name
|
158
|
-
expect(subject).to have_key :age
|
159
|
-
end
|
160
|
-
|
161
|
-
it '#[]' do
|
162
|
-
expect(subject['name']).to eq 'John'
|
163
|
-
expect(subject['age']).to eq 24
|
164
|
-
|
165
|
-
expect(subject[:name]).to eq 'John'
|
166
|
-
expect(subject[:age]).to eq 24
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
context 'with method getter access' do
|
171
|
-
let(:body) do
|
172
|
-
<<-JSON
|
173
|
-
{"name": "John", "age": 24}
|
174
|
-
JSON
|
175
|
-
end
|
176
|
-
|
177
|
-
it '#<method getter>' do
|
178
|
-
expect(subject).to respond_to :name
|
179
|
-
expect(subject).to respond_to :age
|
180
|
-
|
181
|
-
expect(subject.name).to eq 'John'
|
182
|
-
expect(subject.age).to eq 24
|
183
|
-
end
|
184
|
-
end
|
185
144
|
end
|
186
145
|
end
|
187
146
|
end
|