restify 1.9.0.rc1 → 1.13.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 56819d6525aa39551a5d638f500585ca7c06ed931ceb0e272bed65cd823db3c8
4
- data.tar.gz: 803ddcde2d84ceb8b860f73a016844aa2aa08cceeeeec307aa6bc9fde87cf0bf
3
+ metadata.gz: e2b5dacc128de6cbfed604453544f51eaeffd16b9b6cb83f5353ecca66d24a8d
4
+ data.tar.gz: 5c3eba335362aea288f851327fa96262e5b464b9a747b092955241bb362e9c0d
5
5
  SHA512:
6
- metadata.gz: a5e62bcb309b29872ac78da6d4cb3ea489da01fd4501c7fadc6beaa299a4fc6d23e9428eef49d82032c055598bc763a006d3d91c4e102c2f98d22db4d9f7c5c0
7
- data.tar.gz: a5e4ade033f7f83fa5d195dd7d034399e96c561121a756dc995577f8e345a9e5aaac9272818902a4f3b9c742d1018c35ee7a39cee1292f2320eece3ce69810a6
6
+ metadata.gz: 32569c3544a1ac6734b3c81c1e2b6a46ea7dba324c1f71f5e85bd1df93b8b73bb70114a7cec37dd8e38e561a821e674e8c437c78757d78df75e1e51b1a5a79f8
7
+ data.tar.gz: 6f03d156fcc20e0dfba3d7fda0a5c7851ff5d9342fbb9b50c4d90d1f43bf65e92f0ecabb714c4023ce4ca8cfb95b231abd7ea5d1e05339e839ea046b17f3d1fe
@@ -1,82 +1,153 @@
1
1
  # Changelog
2
+ All notable changes to this project will be documented in this file.
2
3
 
3
- ## 1.8.0
4
+ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
5
+ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
4
6
 
5
- * Add HEAD request method (#16)
6
7
 
7
- ## 1.7.0
8
8
 
9
- * Introduce promise dependency timeouts (#15)
9
+ ## Unreleased
10
+ ---
10
11
 
11
- ## 1.6.0
12
+ ### New
12
13
 
13
- * Specify headers on restify clients and individual requests (#14)
14
+ ### Changes
14
15
 
15
- ## 1.5.0
16
+ ### Fixes
16
17
 
17
- * Tune typhoeus adapter to be more race-condition resilent
18
- * Add MessagePack processor enabled by default
18
+ ### Breaks
19
19
 
20
- ## 1.4.4
21
20
 
22
- * Fix race condition in typhoeus adapter
23
- * Add `#request` to `NetworkError` to ease debugging
21
+ ## 1.13.0 - (2020-06-12)
22
+ ---
24
23
 
25
- ## 1.4.3
24
+ ### New
25
+ * typhoeus: Support setting per-request libcurl options on adapter
26
+ * typhoeus: Enable short TCP keepalive probes by default (5s/5s)
26
27
 
27
- * Add advanced logging capabilities using logging gem
28
- * Improve compatibility with webmocks returning `nil` as headers
29
28
 
30
- ## 1.4.1
29
+ ## 1.12.0 - (2020-04-01)
30
+ ---
31
31
 
32
- * Fix possible deadlock issues
32
+ ### Added
33
+ * Explicit exception class for HTTP status code 410 (Gone)
33
34
 
34
- ## 1.4.0
35
+ ### Changed
35
36
 
36
- * Fix possible concurrency issue with typhoeus adapter
37
- * Add timeout option to requests (only supported by typhoeus adapter)
37
+ ### Fixed
38
+ * `GatewayError` exception classes introduced in v1.11.0 now properly inherit from `ServerError` (#30)
38
39
 
39
- ## 1.3.1
40
40
 
41
- * Improve typhoeus adapters initial request queuing
42
- * Disable default pipelining
41
+ ## 1.11.0 - (2019-07-11)
42
+ ### Added
43
+ * Explicit exception classes for HTTP status codes 500, 502, 503, 504
43
44
 
44
- ## 1.3.0
45
+ ## 1.10.0 - 2018-12-11
46
+ ### Changed
47
+ - Raise more specific error on a few status codes (#17)
48
+ - Complete promises with an empty list (but a list) of dependencies (#18)
45
49
 
46
- * Improve typhoeus adapter to better utilize concurrency
47
- * Default to new typhoeus adapter
50
+ ## 1.9.0 - 2018-11-13
51
+ ### Changed
52
+ - Do not raise error on 3XX responses but return responses
48
53
 
49
- ## 1.2.1
54
+ ## 1.8.0 - 2018-08-22
55
+ ### Added
56
+ - Add HEAD request method (#16)
50
57
 
51
- * Fix issue with Ruby 2.2 compatibility
58
+ ## 1.7.0 - 2018-08-15
59
+ ### Added
60
+ - Introduce promise dependency timeouts (#15)
52
61
 
53
- ## 1.2.0
62
+ ## 1.6.0 - 2018-08-09
63
+ ### Changed
64
+ - Specify headers on restify clients and individual requests (#14)
54
65
 
55
- * Add experimental PooledEM adapter (#10)
56
- * Improve marshalling of resources
66
+ ## 1.5.0 - 2018-07-31
67
+ ### Added
68
+ - Add MessagePack processor enabled by default
57
69
 
58
- ## 1.1.0
70
+ ### Changed
71
+ - Tune typhoeus adapter to be more race-condition resilent
59
72
 
60
- * Return response body if no processor matches (#7)
61
- * Add shortcuts for creating fulfilled / rejected promises (#6)
73
+ ## 1.4.4 - 2018-07-13
74
+ ### Added
75
+ - Add `#request` to `NetworkError` to ease debugging
62
76
 
63
- ## 1.0.0
77
+ ### Changed
78
+ - Fix race condition in typhoeus adapter
64
79
 
65
- * Experimental cache API doing nothing for now
66
- * Use `~> 1.0` of `concurrent-ruby`
80
+ ## 1.4.3 - 2017-11-15
81
+ ### Added
82
+ - Add advanced logging capabilities using logging gem
67
83
 
68
- ## 0.5.0
84
+ ### Changed
85
+ - Improve compatibility with webmocks returning `nil` as headers
69
86
 
70
- * Add `sync` option to typhoeus adapter
71
- * Add registry for storing entry points
72
- * Make eventmachine based adapter default
87
+ ## 1.4.1 - 2017-11-15
88
+ ### Changed
89
+ - Fix possible deadlock issues
73
90
 
74
- ## 0.4.0
91
+ ## 1.4.0 - 2017-11-10
92
+ ### Added
93
+ - Add timeout option to requests (only supported by typhoeus adapter)
75
94
 
76
- * Add method to explicit access resource data
77
- * Drop obligation in favor of simple Concurrent::IVar based promise class.
95
+ ### Changed
96
+ - Fix possible concurrency issue with typhoeus adapter
97
+
98
+ ## 1.3.1 - 2017-11-10
99
+ ### Changed
100
+ - Improve typhoeus adapters initial request queuing
101
+ - Disable default pipelining
102
+
103
+ ## 1.3.0 - 2017-11-08
104
+ ### Changed
105
+ - Improve typhoeus adapter to better utilize concurrency
106
+ - Default to new typhoeus adapter
107
+
108
+ ## 1.2.1 - 2017-10-30
109
+ ### Changed
110
+ - Fix issue with Ruby 2.2 compatibility
111
+
112
+ ## 1.2.0 - 2017-10-30
113
+ ### Added
114
+ - Add experimental PooledEM adapter (#10)
115
+
116
+ ### Changed
117
+ - Improve marshaling of resources
118
+
119
+ ## 1.1.0 - 2017-05-12
120
+ ### Added
121
+ - Add shortcuts for creating fulfilled / rejected promises (#6)
122
+
123
+ ### Changed
124
+ - Return response body if no processor matches (#7)
125
+
126
+ ## 1.0.0 - 2016-08-22
127
+ ### Added
128
+ - Experimental cache API doing nothing for now
129
+
130
+ ### Changed
131
+ - Use `~> 1.0` of `concurrent-ruby`
132
+
133
+ ## 0.5.0 - 2016-04-04
134
+ ### Added
135
+ - Add `sync` option to typhoeus adapter
136
+ - Add registry for storing entry points
137
+
138
+ ### Changed
139
+ - Make eventmachine based adapter default
140
+
141
+ ## 0.4.0 - 2016-02-24
142
+ ### Added
143
+ - Add method to explicit access resource data
144
+
145
+ ### Changed
146
+ - Use typhoeus as default adapter
147
+ - `Restify.new` returns relation now instead of resource
148
+
149
+ ### Removed
150
+ - Drop obligation in favor of simple Concurrent::IVar based promise class.
78
151
  Notable changes:
79
- - Returned object us of type `Restify::Promise` now.
80
- - `value` will not raise exception but return `nil` in case of failure. Use `value!` for old behavior.
81
- * Use typhoeus as default adapter
82
- * `Restify.new` returns relation now instead of resource
152
+ - Returned object us of type `Restify::Promise` now.
153
+ - `value` will not raise exception but return `nil` in case of failure. Use `value!` for old behavior.
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Restify
2
2
 
3
3
  [![Build Status](https://travis-ci.org/jgraichen/restify.svg?branch=master)](https://travis-ci.org/jgraichen/restify)
4
+ [![Code Quality](https://codebeat.co/badges/18ffe6b7-8239-493a-b5b6-be329b9f275d)](https://codebeat.co/projects/github-com-jgraichen-restify-master)
4
5
 
5
6
  Restify is an hypermedia REST client that does parallel, concurrent and keep-alive requests by default.
6
7
 
@@ -14,20 +15,17 @@ Restify is build upon the following libraries:
14
15
  * [addressable](https://github.com/sporkmonger/addressable)
15
16
  * [typhoeus](https://github.com/typhoeus/typhoeus)
16
17
 
17
- It has optional HTTP adapters using:
18
-
19
- * [em-http-request](https://github.com/igrigorik/em-http-request)
20
-
21
18
  The HTTP adapters are mostly run in a background thread and may not survive mid-application forks.
22
19
 
23
- Included processors can handle:
20
+ Restify includes processors to parse responses and to extract links between resources. The following formats are can be parsed:
24
21
 
25
- * Plain JSON with GitHub-style relations
26
- * MessagePack with GitHub-style relations *(currently experimental)*
22
+ * JSON
23
+ * MessagePack
27
24
 
28
- (Beside HTTP Link header that's always supported)
25
+ Links are extracted from
29
26
 
30
- Restify requires Ruby 2.0+.
27
+ * HTTP Link header
28
+ * Github-style relations in payloads
31
29
 
32
30
  ### Planned features
33
31
 
@@ -105,9 +103,9 @@ commit = repo.rel(:commits).get.value.first
105
103
  And print it:
106
104
 
107
105
  ```ruby
108
- puts "Last commit: #{commit[:sha]}"
109
- puts "By #{commit[:commit][:author][:name]} <#{commit[:commit][:author][:email]}>"
110
- puts "#{commit[:commit][:message]}"
106
+ puts "Last commit: #{commit['sha']}"
107
+ puts "By #{commit['commit']['author']['name']} <#{commit['commit']['author']['email']}>"
108
+ puts "#{commit['commit']['message']}"
111
109
  ```
112
110
 
113
111
  See commented example in main spec [`spec/restify_spec.rb`](https://github.com/jgraichen/restify/blob/master/spec/restify_spec.rb#L100) or in the `examples` directory.
@@ -63,8 +63,8 @@ module Restify
63
63
  query: request.uri.normalized_query,
64
64
  body: request.body,
65
65
  head: request.headers
66
- rescue Exception => err # rubocop:disable RescueException
67
- writer.reject err
66
+ rescue Exception => e # rubocop:disable Lint/RescueException
67
+ writer.reject e
68
68
  requests.shift unless pipeline?
69
69
  return
70
70
  end
@@ -200,9 +200,9 @@ module Restify
200
200
  @pool = Pool.new(**kwargs)
201
201
  end
202
202
 
203
- # rubocop:disable MethodLength
204
- # rubocop:disable AbcSize
205
- # rubocop:disable BlockLength
203
+ # rubocop:disable Metrics/MethodLength
204
+ # rubocop:disable Metrics/AbcSize
205
+ # rubocop:disable Metrics/BlockLength
206
206
  def call_native(request, writer)
207
207
  next_tick do
208
208
  defer = @pool.get(request)
@@ -241,9 +241,9 @@ module Restify
241
241
  @pool.remove(conn)
242
242
  writer.reject(req.error)
243
243
  end
244
- rescue Exception => ex # rubocop:disable RescueException
244
+ rescue Exception => e # rubocop:disable Lint/RescueException
245
245
  @pool.remove(conn)
246
- writer.reject(ex)
246
+ writer.reject(e)
247
247
  end
248
248
  end
249
249
  end
@@ -16,19 +16,28 @@ module Restify
16
16
  'Transfer-Encoding' => ''
17
17
  }.freeze
18
18
 
19
- def initialize(sync: false, **options)
20
- @sync = sync
21
- @hydra = ::Typhoeus::Hydra.new(**options)
22
- @mutex = Mutex.new
23
- @signal = ConditionVariable.new
19
+ DEFAULT_OPTIONS = {
20
+ followlocation: true,
21
+ tcp_keepalive: true,
22
+ tcp_keepidle: 5,
23
+ tcp_keepintvl: 5
24
+ }.freeze
25
+
26
+ def initialize(sync: false, options: {}, **kwargs)
27
+ @sync = sync
28
+ @hydra = ::Typhoeus::Hydra.new(**kwargs)
29
+ @mutex = Mutex.new
30
+ @signal = ConditionVariable.new
31
+ @thread = nil
32
+ @options = DEFAULT_OPTIONS.merge(options)
24
33
  end
25
34
 
26
35
  def sync?
27
36
  @sync
28
37
  end
29
38
 
30
- # rubocop:disable AbcSize
31
- # rubocop:disable MethodLength
39
+ # rubocop:disable Metrics/AbcSize
40
+ # rubocop:disable Metrics/MethodLength
32
41
  def call_native(request, writer)
33
42
  req = convert(request, writer)
34
43
 
@@ -56,15 +65,15 @@ module Restify
56
65
 
57
66
  private
58
67
 
59
- # rubocop:disable AbcSize
60
- # rubocop:disable MethodLength
68
+ # rubocop:disable Metrics/AbcSize
69
+ # rubocop:disable Metrics/MethodLength
61
70
  def convert(request, writer)
62
71
  ::Typhoeus::Request.new(
63
72
  request.uri,
73
+ **@options,
64
74
  method: request.method,
65
75
  headers: DEFAULT_HEADERS.merge(request.headers),
66
76
  body: request.body,
67
- followlocation: true,
68
77
  timeout: request.timeout,
69
78
  connecttimeout: request.timeout
70
79
  ).tap do |req|
@@ -123,7 +132,7 @@ module Restify
123
132
  @hydra.queued_requests.any? || @hydra.multi.easy_handles.any?
124
133
  end
125
134
 
126
- # rubocop:disable MethodLength
135
+ # rubocop:disable Metrics/MethodLength
127
136
  def _run
128
137
  debug 'hydra:run'
129
138
  @hydra.run while _ongoing?
@@ -36,7 +36,7 @@ module Restify
36
36
 
37
37
  def inherit(uri, **kwargs)
38
38
  uri ||= self.uri
39
- Context.new uri, kwargs.merge(options)
39
+ Context.new(uri, **kwargs, **options)
40
40
  end
41
41
 
42
42
  def process(response)
@@ -62,7 +62,7 @@ module Restify
62
62
  if !response.errored?
63
63
  process response
64
64
  else
65
- Context.raise_response_error(response)
65
+ raise ResponseError.from_code(response)
66
66
  end
67
67
  end
68
68
  end
@@ -101,18 +101,5 @@ module Restify
101
101
  def default_headers
102
102
  options.fetch(:headers, {})
103
103
  end
104
-
105
- class << self
106
- def raise_response_error(response)
107
- case response.code
108
- when 400...500
109
- raise ClientError.new(response)
110
- when 500...600
111
- raise ServerError.new(response)
112
- else
113
- raise "Unknown response code: #{response.code}"
114
- end
115
- end
116
- end
117
104
  end
118
105
  end
@@ -20,6 +20,37 @@ module Restify
20
20
  class ResponseError < StandardError
21
21
  attr_reader :response
22
22
 
23
+ def self.from_code(response)
24
+ case response.code
25
+ when 400
26
+ BadRequest.new(response)
27
+ when 401
28
+ Unauthorized.new(response)
29
+ when 404
30
+ NotFound.new(response)
31
+ when 406
32
+ NotAcceptable.new(response)
33
+ when 410
34
+ Gone.new(response)
35
+ when 422
36
+ UnprocessableEntity.new(response)
37
+ when 400...500
38
+ ClientError.new(response)
39
+ when 500
40
+ InternalServerError.new(response)
41
+ when 502
42
+ BadGateway.new(response)
43
+ when 503
44
+ ServiceUnavailable.new(response)
45
+ when 504
46
+ GatewayTimeout.new(response)
47
+ when 500...600
48
+ ServerError.new(response)
49
+ else
50
+ raise "Unknown response code: #{response.code}"
51
+ end
52
+ end
53
+
23
54
  def initialize(response)
24
55
  @response = response
25
56
  super "#{response.message} (#{response.code}) for `#{response.uri}':\n" \
@@ -65,4 +96,29 @@ module Restify
65
96
  # A {ServerError} will be raised when a response has a
66
97
  # 5XX status code.
67
98
  class ServerError < ResponseError; end
99
+
100
+ # A {GatewayError} is the common base class for 502, 503 and 504
101
+ # response codes often used by load balancers when upstream servers are
102
+ # failing or not available.
103
+ #
104
+ # This can be used to catch "common" gateway responses.
105
+ class GatewayError < ServerError; end
106
+
107
+ ###
108
+ # CONCRETE SUBCLASSES FOR TYPICAL STATUS CODES
109
+ #
110
+ # This makes it easy to rescue specific expected error types.
111
+
112
+ class BadRequest < ClientError; end
113
+ class Unauthorized < ClientError; end
114
+ class NotFound < ClientError; end
115
+ class NotAcceptable < ClientError; end
116
+ class Gone < ClientError; end
117
+ class UnprocessableEntity < ClientError; end
118
+
119
+ class InternalServerError < ServerError; end
120
+
121
+ class BadGateway < GatewayError; end
122
+ class ServiceUnavailable < GatewayError; end
123
+ class GatewayTimeout < GatewayError; end
68
124
  end
@@ -39,9 +39,9 @@ module Restify
39
39
 
40
40
  def resolve_context(uri, **opts)
41
41
  if uri.is_a? Symbol
42
- Restify::Registry.fetch(uri).inherit(nil, opts)
42
+ Restify::Registry.fetch(uri).inherit(nil, **opts)
43
43
  else
44
- Context.new uri, opts
44
+ Context.new(uri, **opts)
45
45
  end
46
46
  end
47
47
  end
@@ -25,10 +25,10 @@ module Restify
25
25
  end
26
26
 
27
27
  class << self
28
- REGEXP_URI = /<[^>]*>\s*/
29
- REGEXP_PAR = /;\s*\w+\s*=\s*/i
30
- REGEXP_QUT = /"[^"]*"\s*/
31
- REGEXP_ARG = /\w+\s*/i
28
+ REGEXP_URI = /<[^>]*>\s*/.freeze
29
+ REGEXP_PAR = /;\s*\w+\s*=\s*/i.freeze
30
+ REGEXP_QUT = /"[^"]*"\s*/.freeze
31
+ REGEXP_ARG = /\w+\s*/i.freeze
32
32
 
33
33
  def parse(string)
34
34
  scanner = StringScanner.new(string.strip)
@@ -7,6 +7,13 @@ module Restify
7
7
  @dependencies = dependencies.flatten
8
8
 
9
9
  super(&nil)
10
+
11
+ # When dependencies were passed in, but none are left after flattening,
12
+ # then we don't have to wait for explicit dependencies or resolution
13
+ # through a writer.
14
+ if !@task && @dependencies.empty? && dependencies.any?
15
+ complete true, [], nil
16
+ end
10
17
  end
11
18
 
12
19
  def wait(timeout = nil)
@@ -16,6 +23,7 @@ module Restify
16
23
 
17
24
  super
18
25
  raise t if incomplete?
26
+
19
27
  self
20
28
  end
21
29
 
@@ -79,6 +79,7 @@ module Restify
79
79
 
80
80
  def convert_param(value)
81
81
  return value.to_param.to_s if value.respond_to?(:to_param)
82
+
82
83
  value
83
84
  end
84
85
 
@@ -61,6 +61,7 @@ module Restify
61
61
  class << self
62
62
  def new(timeout, *args)
63
63
  return timeout if timeout.is_a?(self)
64
+
64
65
  super
65
66
  end
66
67
  end
@@ -3,9 +3,9 @@
3
3
  module Restify
4
4
  module VERSION
5
5
  MAJOR = 1
6
- MINOR = 9
6
+ MINOR = 13
7
7
  PATCH = 0
8
- STAGE = :rc1
8
+ STAGE = nil
9
9
  STRING = [MAJOR, MINOR, PATCH, STAGE].reject(&:nil?).join('.').freeze
10
10
 
11
11
  def self.to_s
@@ -47,7 +47,7 @@ describe Restify::Context do
47
47
 
48
48
  context 'YAML' do
49
49
  let(:dump) { YAML.dump(context) }
50
- let(:load) { YAML.load(dump) } # rubocop:disable YAMLLoad
50
+ let(:load) { YAML.load(dump) } # rubocop:disable Security/YAMLLoad
51
51
 
52
52
  subject { load }
53
53
 
@@ -56,7 +56,7 @@ describe Restify::Context do
56
56
 
57
57
  context 'Marshall' do
58
58
  let(:dump) { Marshal.dump(context) }
59
- let(:load) { Marshal.load(dump) } # rubocop:disable MarshalLoad
59
+ let(:load) { Marshal.load(dump) } # rubocop:disable Security/MarshalLoad
60
60
 
61
61
  subject { load }
62
62
 
@@ -0,0 +1,70 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Restify::ResponseError do
6
+ let(:response) { double 'response' }
7
+ let(:message) { 'Error' }
8
+ let(:uri) { 'http://localhost' }
9
+
10
+ before do
11
+ allow(response).to receive(:uri).and_return(uri)
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({})
15
+ end
16
+
17
+ describe '.from_code' do
18
+ subject(:err) { described_class.from_code(response) }
19
+
20
+ context 'with 400 Bad Request' do
21
+ let(:code) { 400 }
22
+ it { is_expected.to be_a ::Restify::BadRequest }
23
+ end
24
+
25
+ context 'with 401 Unauthorized' do
26
+ let(:code) { 401 }
27
+ it { is_expected.to be_a ::Restify::Unauthorized }
28
+ end
29
+
30
+ context 'with 404 Unauthorized' do
31
+ let(:code) { 404 }
32
+ it { is_expected.to be_a ::Restify::NotFound }
33
+ end
34
+
35
+ context 'with 406 Not Acceptable' do
36
+ let(:code) { 406 }
37
+ it { is_expected.to be_a ::Restify::NotAcceptable }
38
+ end
39
+
40
+ context 'with 410 Gone' do
41
+ let(:code) { 410 }
42
+ it { is_expected.to be_a ::Restify::Gone }
43
+ end
44
+
45
+ context 'with 422 Unprocessable Entity' do
46
+ let(:code) { 422 }
47
+ it { is_expected.to be_a ::Restify::UnprocessableEntity }
48
+ end
49
+
50
+ context 'with 500 Internal Server Error' do
51
+ let(:code) { 500 }
52
+ it { is_expected.to be_a ::Restify::InternalServerError }
53
+ end
54
+
55
+ context 'with 502 Bad Gateway' do
56
+ let(:code) { 502 }
57
+ it { is_expected.to be_a ::Restify::BadGateway }
58
+ end
59
+
60
+ context 'with 503 Service Unavailable' do
61
+ let(:code) { 503 }
62
+ it { is_expected.to be_a ::Restify::ServiceUnavailable }
63
+ end
64
+
65
+ context 'with 504 Gateway Timeout' do
66
+ let(:code) { 504 }
67
+ it { is_expected.to be_a ::Restify::GatewayTimeout }
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Restify do
6
+ let!(:request_stub) do
7
+ stub_request(:get, 'http://localhost/base')
8
+ .to_return do
9
+ <<-RESPONSE.gsub(/^ {8}/, '')
10
+ HTTP/1.1 #{http_status}
11
+ Content-Length: 333
12
+ Transfer-Encoding: chunked
13
+ Link: <http://localhost/other>; rel="neat"
14
+ RESPONSE
15
+ end
16
+ end
17
+
18
+ let(:http_status) { '200 OK' }
19
+
20
+ describe 'Error handling' do
21
+ subject(:request) { Restify.new('http://localhost/base').get.value! }
22
+
23
+ context 'for 400 status codes' do
24
+ let(:http_status) { '400 Bad Request' }
25
+
26
+ it 'throws a BadRequest exception' do
27
+ expect { request }.to raise_error Restify::BadRequest
28
+ end
29
+ end
30
+
31
+ context 'for 401 status codes' do
32
+ let(:http_status) { '401 Unauthorized' }
33
+
34
+ it 'throws an Unauthorized exception' do
35
+ expect { request }.to raise_error Restify::Unauthorized
36
+ end
37
+ end
38
+
39
+ context 'for 404 status codes' do
40
+ let(:http_status) { '404 Not Found' }
41
+
42
+ it 'throws a ClientError exception' do
43
+ expect { request }.to raise_error Restify::NotFoundError
44
+ end
45
+ end
46
+
47
+ context 'for 406 status codes' do
48
+ let(:http_status) { '406 Not Acceptable' }
49
+
50
+ it 'throws a NotAcceptable exception' do
51
+ expect { request }.to raise_error Restify::NotAcceptable
52
+ end
53
+ end
54
+
55
+ context 'for 422 status codes' do
56
+ let(:http_status) { '422 Unprocessable Entity' }
57
+
58
+ it 'throws a UnprocessableEntity exception' do
59
+ expect { request }.to raise_error Restify::UnprocessableEntity
60
+ end
61
+ end
62
+
63
+ context 'for any other 4xx status codes' do
64
+ let(:http_status) { '415 Unsupported Media Type' }
65
+
66
+ it 'throws a generic ClientError exception' do
67
+ expect { request }.to raise_error Restify::ClientError
68
+ end
69
+ end
70
+
71
+ context 'for any 5xx status codes' do
72
+ let(:http_status) { '500 Internal Server Error' }
73
+
74
+ it 'throws a generic ServerError exception' do
75
+ expect { request }.to raise_error Restify::ServerError
76
+ end
77
+ end
78
+ end
79
+ end
@@ -26,7 +26,7 @@ describe Restify::Global do
26
26
  let(:options) { {accept: 'application.vnd.github.v3+json'} }
27
27
  let(:context) { Restify::Context.new uri, **options }
28
28
 
29
- subject { global.new name, options }
29
+ subject { global.new(name, **options) }
30
30
 
31
31
  it 'returns relation for stored registry item' do
32
32
  Restify::Registry.store name, uri, options
@@ -163,6 +163,13 @@ describe Restify::Promise do
163
163
  expect(subject).to eq 17
164
164
  end
165
165
  end
166
+
167
+ # Nobody does this explicitly, but it can happen when the array of
168
+ # dependencies is built dynamically.
169
+ context 'with an empty array of dependencies and without task' do
170
+ subject { described_class.new([]).value! }
171
+ it { is_expected.to eq [] }
172
+ end
166
173
  end
167
174
 
168
175
  describe '#wait' do
@@ -134,7 +134,6 @@ describe Restify do
134
134
  # the result is here.
135
135
  expect { create_user_promise.value! }.to \
136
136
  raise_error(Restify::ClientError) do |e|
137
-
138
137
  # Because we forgot to send a "name" the server complains
139
138
  # with an error code that will lead to a raised error.
140
139
 
@@ -206,7 +205,6 @@ describe Restify do
206
205
 
207
206
  expect { create_user_promise.value! }.to \
208
207
  raise_error(Restify::ClientError) do |e|
209
-
210
208
  expect(e.status).to eq :unprocessable_entity
211
209
  expect(e.code).to eq 422
212
210
  expect(e.errors).to eq 'name' => ["can't be blank"]
@@ -3,11 +3,14 @@
3
3
  require 'rspec'
4
4
  require 'webmock/rspec'
5
5
 
6
- if ENV['CI'] || (defined?(:RUBY_ENGINE) && RUBY_ENGINE != 'rbx')
7
- require 'coveralls'
8
- Coveralls.wear! do
9
- add_filter 'spec'
10
- end
6
+ require 'simplecov'
7
+ SimpleCov.start do
8
+ add_filter 'spec'
9
+ end
10
+
11
+ if ENV['CI']
12
+ require 'codecov'
13
+ SimpleCov.formatter = SimpleCov::Formatter::Codecov
11
14
  end
12
15
 
13
16
  require 'restify'
@@ -35,7 +38,7 @@ require 'webmock/rspec'
35
38
  require 'rspec/collection_matchers'
36
39
  require 'em-synchrony'
37
40
 
38
- Dir[File.expand_path('spec/support/**/*.rb')].each {|f| require f }
41
+ Dir[File.expand_path('spec/support/**/*.rb')].sort.each {|f| require f }
39
42
 
40
43
  RSpec.configure do |config|
41
44
  config.order = 'random'
@@ -51,6 +54,7 @@ RSpec.configure do |config|
51
54
  ::Logging.logger.root.add_appenders ::Logging.appenders.stdout
52
55
  end
53
56
 
57
+ config.warnings = true
54
58
  config.after(:suite) do
55
59
  EventMachine.stop if defined?(EventMachine) && EventMachine.reactor_running?
56
60
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: restify
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0.rc1
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jan Graichen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-16 00:00:00.000000000 Z
11
+ date: 2020-06-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -56,16 +56,22 @@ dependencies:
56
56
  name: hashie
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
61
  version: '3.3'
62
+ - - "<"
63
+ - !ruby/object:Gem::Version
64
+ version: '5.0'
62
65
  type: :runtime
63
66
  prerelease: false
64
67
  version_requirements: !ruby/object:Gem::Requirement
65
68
  requirements:
66
- - - "~>"
69
+ - - ">="
67
70
  - !ruby/object:Gem::Version
68
71
  version: '3.3'
72
+ - - "<"
73
+ - !ruby/object:Gem::Version
74
+ version: '5.0'
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: rack
71
77
  requirement: !ruby/object:Gem::Requirement
@@ -140,16 +146,16 @@ dependencies:
140
146
  name: bundler
141
147
  requirement: !ruby/object:Gem::Requirement
142
148
  requirements:
143
- - - "~>"
149
+ - - ">="
144
150
  - !ruby/object:Gem::Version
145
- version: '1.5'
151
+ version: '0'
146
152
  type: :development
147
153
  prerelease: false
148
154
  version_requirements: !ruby/object:Gem::Requirement
149
155
  requirements:
150
- - - "~>"
156
+ - - ">="
151
157
  - !ruby/object:Gem::Version
152
- version: '1.5'
158
+ version: '0'
153
159
  description: An experimental hypermedia REST client that uses parallel, keep-alive
154
160
  and pipelined requests by default.
155
161
  email:
@@ -186,8 +192,10 @@ files:
186
192
  - lib/restify/version.rb
187
193
  - spec/restify/cache_spec.rb
188
194
  - spec/restify/context_spec.rb
195
+ - spec/restify/error_spec.rb
189
196
  - spec/restify/features/head_requests_spec.rb
190
197
  - spec/restify/features/request_headers_spec.rb
198
+ - spec/restify/features/response_errors.rb
191
199
  - spec/restify/global_spec.rb
192
200
  - spec/restify/link_spec.rb
193
201
  - spec/restify/processors/base_spec.rb
@@ -215,20 +223,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
215
223
  version: '0'
216
224
  required_rubygems_version: !ruby/object:Gem::Requirement
217
225
  requirements:
218
- - - ">"
226
+ - - ">="
219
227
  - !ruby/object:Gem::Version
220
- version: 1.3.1
228
+ version: '0'
221
229
  requirements: []
222
- rubyforge_project:
223
- rubygems_version: 2.7.7
230
+ rubygems_version: 3.1.2
224
231
  signing_key:
225
232
  specification_version: 4
226
233
  summary: An experimental hypermedia REST client.
227
234
  test_files:
228
235
  - spec/restify/cache_spec.rb
229
236
  - spec/restify/context_spec.rb
237
+ - spec/restify/error_spec.rb
230
238
  - spec/restify/features/head_requests_spec.rb
231
239
  - spec/restify/features/request_headers_spec.rb
240
+ - spec/restify/features/response_errors.rb
232
241
  - spec/restify/global_spec.rb
233
242
  - spec/restify/link_spec.rb
234
243
  - spec/restify/processors/base_spec.rb