restify 2.1.0 → 3.0.0.rc2
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 +48 -0
- data/README.md +30 -4
- data/lib/restify/adapter/base.rb +10 -1
- data/lib/restify/adapter/ethon.rb +462 -0
- data/lib/restify/adapter/loop_lock.rb +124 -0
- data/lib/restify/adapter/telemetry.rb +6 -4
- data/lib/restify/adapter/typhoeus.rb +48 -23
- data/lib/restify/context.rb +5 -5
- data/lib/restify/error.rb +13 -0
- data/lib/restify/global.rb +9 -30
- data/lib/restify/logging.rb +10 -4
- data/lib/restify/processors/base/parsing.rb +13 -1
- data/lib/restify/promise.rb +20 -2
- data/lib/restify/registry.rb +2 -2
- data/lib/restify/relation.rb +8 -8
- data/lib/restify/request.rb +2 -2
- data/lib/restify/resource.rb +20 -2
- data/lib/restify/response.rb +39 -3
- data/lib/restify/timeout.rb +11 -5
- data/lib/restify/version.rb +3 -3
- data/lib/restify/webmock.rb +126 -0
- data/lib/restify.rb +5 -1
- data/spec/restify/adapter/ethon_spec.rb +263 -0
- data/spec/restify/adapter/loop_lock_spec.rb +144 -0
- data/spec/restify/adapter/telemetry_spec.rb +61 -0
- data/spec/restify/adapter/typhoeus_spec.rb +26 -0
- data/spec/restify/cache_spec.rb +1 -3
- data/spec/restify/context_spec.rb +55 -0
- data/spec/restify/features/protocols_spec.rb +28 -0
- data/spec/restify/features/redirects_spec.rb +45 -0
- data/spec/restify/features/request_errors_spec.rb +1 -1
- data/spec/restify/features/response_bodies_spec.rb +45 -0
- data/spec/restify/features/response_encoding_spec.rb +82 -0
- data/spec/restify/features/response_errors_spec.rb +22 -1
- data/spec/restify/features/webmock_spec.rb +92 -1
- data/spec/restify/global_spec.rb +78 -10
- data/spec/restify/processors/json_spec.rb +36 -0
- data/spec/restify/processors/msgpack_spec.rb +36 -0
- data/spec/restify/promise_spec.rb +82 -0
- data/spec/restify/relation_spec.rb +2 -6
- data/spec/restify/request_spec.rb +26 -0
- data/spec/restify/timeout_spec.rb +11 -0
- data/spec/spec_helper.rb +10 -6
- data/spec/support/stub_server.rb +4 -4
- metadata +26 -209
- data/vendor/bundle/ruby/4.0.0/bundler/gems/my-rubocop-2b861962124a/LICENSE +0 -21
- data/vendor/bundle/ruby/4.0.0/bundler/gems/my-rubocop-2b861962124a/README.md +0 -23
- data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/CHANGELOG.md +0 -561
- data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/MIT-LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/README.rdoc +0 -40
- data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/CHANGELOG.md +0 -326
- data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/LICENSE.txt +0 -202
- data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/README.md +0 -121
- data/vendor/bundle/ruby/4.0.0/gems/ast-2.4.3/LICENSE.MIT +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/ast-2.4.3/README.YARD.md +0 -12
- data/vendor/bundle/ruby/4.0.0/gems/base64-0.3.0/README.md +0 -48
- data/vendor/bundle/ruby/4.0.0/gems/bigdecimal-4.1.2/LICENSE +0 -56
- data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/CHANGELOG.md +0 -615
- data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/LICENSE.txt +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/README.md +0 -409
- data/vendor/bundle/ruby/4.0.0/gems/connection_pool-3.0.2/LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/connection_pool-3.0.2/README.md +0 -182
- data/vendor/bundle/ruby/4.0.0/gems/crack-1.0.1/LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/crack-1.0.1/README.md +0 -43
- data/vendor/bundle/ruby/4.0.0/gems/diff-lcs-1.6.2/CHANGELOG.md +0 -518
- data/vendor/bundle/ruby/4.0.0/gems/diff-lcs-1.6.2/README.md +0 -92
- data/vendor/bundle/ruby/4.0.0/gems/docile-1.4.1/LICENSE +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/docile-1.4.1/README.md +0 -409
- data/vendor/bundle/ruby/4.0.0/gems/drb-2.2.3/LICENSE.txt +0 -22
- data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/CHANGELOG.md +0 -417
- data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/README.md +0 -118
- data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/CHANGELOG.md +0 -507
- data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/LICENSE +0 -24
- data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/LICENSE.SPECS +0 -22
- data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/README.md +0 -138
- data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/LICENSE +0 -19
- data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/README.md +0 -323
- data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/changelog.md +0 -127
- data/vendor/bundle/ruby/4.0.0/gems/hitimes-3.2.0/LICENSE.txt +0 -16
- data/vendor/bundle/ruby/4.0.0/gems/hitimes-3.2.0/README.md +0 -187
- data/vendor/bundle/ruby/4.0.0/gems/i18n-1.15.2/MIT-LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/i18n-1.15.2/README.md +0 -139
- data/vendor/bundle/ruby/4.0.0/gems/json-2.19.9/README.md +0 -310
- data/vendor/bundle/ruby/4.0.0/gems/language_server-protocol-3.17.0.5/LICENSE.txt +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/language_server-protocol-3.17.0.5/README.md +0 -88
- data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/CHANGELOG.md +0 -15
- data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/LICENSE.txt +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/README.md +0 -173
- data/vendor/bundle/ruby/4.0.0/gems/little-plugger-1.1.4/README.rdoc +0 -53
- data/vendor/bundle/ruby/4.0.0/gems/logger-1.7.0/README.md +0 -104
- data/vendor/bundle/ruby/4.0.0/gems/logging-2.4.0/LICENSE +0 -22
- data/vendor/bundle/ruby/4.0.0/gems/logging-2.4.0/README.md +0 -140
- data/vendor/bundle/ruby/4.0.0/gems/minitest-6.0.6/README.rdoc +0 -763
- data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/ChangeLog +0 -383
- data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/LICENSE +0 -177
- data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/README.md +0 -302
- data/vendor/bundle/ruby/4.0.0/gems/multi_json-1.21.1/LICENSE.md +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/multi_json-1.21.1/README.md +0 -281
- data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/ext/libev/LICENSE +0 -37
- data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/ext/libev/README +0 -59
- data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/license.md +0 -80
- data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/readme.md +0 -91
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/CHANGELOG.md +0 -219
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/LICENSE +0 -201
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/README.md +0 -68
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/CHANGELOG.md +0 -110
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/LICENSE +0 -201
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/README.md +0 -62
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/CHANGELOG.md +0 -97
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/LICENSE +0 -201
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/README.md +0 -155
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/CHANGELOG.md +0 -192
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/LICENSE +0 -201
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/README.md +0 -66
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/CHANGELOG.md +0 -31
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/LICENSE +0 -201
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/README.md +0 -40
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/CHANGELOG.md +0 -302
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/LICENSE +0 -201
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/README.md +0 -101
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/CHANGELOG.md +0 -65
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/LICENSE +0 -201
- data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/README.md +0 -115
- data/vendor/bundle/ruby/4.0.0/gems/parallel-2.1.0/MIT-LICENSE.txt +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/parser-3.3.11.1/LICENSE.txt +0 -26
- data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/CHANGELOG.md +0 -786
- data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/LICENSE.md +0 -7
- data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/README.md +0 -143
- data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/CHANGELOG.md +0 -649
- data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/LICENSE.txt +0 -22
- data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/README.md +0 -231
- data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/LICENSE +0 -29
- data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/README.md +0 -484
- data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/docs/jungle/README.md +0 -9
- data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/docs/jungle/rc.d/README.md +0 -74
- data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/ChangeLog +0 -846
- data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/README.ja.rdoc +0 -58
- data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/README.rdoc +0 -60
- data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/CHANGELOG.md +0 -1346
- data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/MIT-LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/README.md +0 -384
- data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/Changelog.md +0 -101
- data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/README.markdown +0 -227
- data/vendor/bundle/ruby/4.0.0/gems/rake-13.4.2/MIT-LICENSE +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/rake-13.4.2/README.rdoc +0 -155
- data/vendor/bundle/ruby/4.0.0/gems/rake-release-1.4.0/LICENSE +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/rake-release-1.4.0/README.md +0 -107
- data/vendor/bundle/ruby/4.0.0/gems/regexp_parser-2.12.0/LICENSE +0 -22
- data/vendor/bundle/ruby/4.0.0/gems/rexml-3.4.4/LICENSE.txt +0 -22
- data/vendor/bundle/ruby/4.0.0/gems/rexml-3.4.4/README.md +0 -57
- data/vendor/bundle/ruby/4.0.0/gems/rspec-3.13.2/LICENSE.md +0 -27
- data/vendor/bundle/ruby/4.0.0/gems/rspec-3.13.2/README.md +0 -47
- data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/Changelog.md +0 -2447
- data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/LICENSE.md +0 -26
- data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/README.md +0 -389
- data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/Changelog.md +0 -1366
- data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/LICENSE.md +0 -25
- data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/README.md +0 -326
- data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/Changelog.md +0 -1351
- data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/LICENSE.md +0 -25
- data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/README.md +0 -465
- data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/Changelog.md +0 -444
- data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/LICENSE.md +0 -23
- data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/README.md +0 -40
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-1.88.0/LICENSE.txt +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-1.88.0/README.md +0 -255
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-ast-1.49.1/LICENSE.txt +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-ast-1.49.1/README.md +0 -54
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/CHANGELOG.md +0 -116
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/MIT-LICENSE.md +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/README.md +0 -91
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/CHANGELOG.md +0 -135
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/MIT-LICENSE.md +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/README.md +0 -91
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-performance-1.26.1/LICENSE.txt +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-performance-1.26.1/README.md +0 -100
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/CHANGELOG.md +0 -1136
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/MIT-LICENSE.md +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/README.md +0 -112
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/CHANGELOG.md +0 -98
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/MIT-LICENSE.md +0 -21
- data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/README.md +0 -93
- data/vendor/bundle/ruby/4.0.0/gems/ruby-progressbar-1.13.0/LICENSE.txt +0 -19
- data/vendor/bundle/ruby/4.0.0/gems/ruby-progressbar-1.13.0/README.md +0 -131
- data/vendor/bundle/ruby/4.0.0/gems/securerandom-0.4.1/README.md +0 -72
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/CHANGELOG.md +0 -191
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/README.md +0 -974
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-cobertura-3.2.0/LICENSE +0 -202
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-cobertura-3.2.0/README.md +0 -65
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/CHANGELOG.md +0 -114
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/README.md +0 -30
- data/vendor/bundle/ruby/4.0.0/gems/simplecov_json_formatter-0.1.4/CHANGELOG.md +0 -13
- data/vendor/bundle/ruby/4.0.0/gems/simplecov_json_formatter-0.1.4/README.md +0 -29
- data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/CHANGELOG.md +0 -465
- data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/LICENSE +0 -22
- data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/README.md +0 -588
- data/vendor/bundle/ruby/4.0.0/gems/tzinfo-2.0.6/LICENSE +0 -19
- data/vendor/bundle/ruby/4.0.0/gems/tzinfo-2.0.6/README.md +0 -406
- data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/CHANGELOG.md +0 -299
- data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/MIT-LICENSE.txt +0 -22
- data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/README.md +0 -194
- data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/CHANGELOG.md +0 -202
- data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/MIT-LICENSE.txt +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/README.md +0 -205
- data/vendor/bundle/ruby/4.0.0/gems/uri-1.1.1/README.md +0 -55
- data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/CHANGELOG.md +0 -2148
- data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/LICENSE +0 -20
- data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/README.md +0 -1229
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Restify
|
|
4
|
+
module Adapter
|
|
5
|
+
#
|
|
6
|
+
# Manages coordination for exclusive ownership of an event loop,
|
|
7
|
+
# shared between a background thread and threads waiting on results.
|
|
8
|
+
# This way, the event loop can run on waiting threads directly,
|
|
9
|
+
# avoiding costly context switches to the background thread.
|
|
10
|
+
#
|
|
11
|
+
# Waiting threads have priority: the background thread only acquires
|
|
12
|
+
# the loop while no thread is waiting for it, and is interrupted to
|
|
13
|
+
# release it as soon as one is.
|
|
14
|
+
#
|
|
15
|
+
# Waiting threads can give up waiting once their result is
|
|
16
|
+
# available, e.g. because another thread running the loop produced
|
|
17
|
+
# it. Whoever runs the loop must call `#notify` after producing a
|
|
18
|
+
# result.
|
|
19
|
+
#
|
|
20
|
+
class LoopLock
|
|
21
|
+
# @yield Called when a waiting thread needs the background thread to
|
|
22
|
+
# release the loop, e.g. to wake it up from `select`.
|
|
23
|
+
#
|
|
24
|
+
def initialize(&interrupt)
|
|
25
|
+
@interrupt = interrupt
|
|
26
|
+
|
|
27
|
+
reset!
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
# Acquire the loop for a thread waiting on a result.
|
|
31
|
+
#
|
|
32
|
+
# @param timeout [Restify::Timeout, Numeric] Maximum time to wait,
|
|
33
|
+
# derived from the promise timeout of the waiting thread.
|
|
34
|
+
#
|
|
35
|
+
# @yieldreturn [Boolean] Whether the result is available, and
|
|
36
|
+
# the loop is not needed anymore.
|
|
37
|
+
#
|
|
38
|
+
# @return [Boolean] true when the calling thread holds the loop,
|
|
39
|
+
# false when the result is available or the timeout expired
|
|
40
|
+
# first.
|
|
41
|
+
#
|
|
42
|
+
def acquire(timeout, &done)
|
|
43
|
+
timeout = Timeout.new(timeout)
|
|
44
|
+
|
|
45
|
+
background = @mutex.synchronize do
|
|
46
|
+
@waiters += 1
|
|
47
|
+
@background
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
@interrupt&.call if background
|
|
51
|
+
|
|
52
|
+
@mutex.synchronize do
|
|
53
|
+
loop do
|
|
54
|
+
return false if done&.call
|
|
55
|
+
|
|
56
|
+
remaining = timeout.remaining
|
|
57
|
+
return false unless remaining.positive?
|
|
58
|
+
|
|
59
|
+
if free?
|
|
60
|
+
@owner = Thread.current
|
|
61
|
+
return true
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
@changed.wait(@mutex, remaining)
|
|
65
|
+
end
|
|
66
|
+
ensure
|
|
67
|
+
@waiters -= 1
|
|
68
|
+
|
|
69
|
+
# Let the background thread continue.
|
|
70
|
+
@changed.broadcast if @waiters.zero?
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Acquire the loop for the background thread. Blocks while any
|
|
75
|
+
# other thread holds the loop or waits for it.
|
|
76
|
+
def acquire_background
|
|
77
|
+
@mutex.synchronize do
|
|
78
|
+
@changed.wait(@mutex) until free? && @waiters.zero?
|
|
79
|
+
|
|
80
|
+
@owner = Thread.current
|
|
81
|
+
@background = true
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def release
|
|
86
|
+
@mutex.synchronize do
|
|
87
|
+
@owner = nil
|
|
88
|
+
@background = false
|
|
89
|
+
@changed.broadcast
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def owned?
|
|
94
|
+
@owner.equal?(Thread.current)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def notify
|
|
98
|
+
return unless @waiters.positive?
|
|
99
|
+
|
|
100
|
+
@mutex.synchronize { @changed.broadcast }
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
# Forget all threads holding or waiting for the loop, e.g. in a
|
|
104
|
+
# forked child process, where these threads do not exist.
|
|
105
|
+
#
|
|
106
|
+
# Must not be called while other threads use the lock.
|
|
107
|
+
def reset!
|
|
108
|
+
@mutex = Mutex.new
|
|
109
|
+
@changed = ConditionVariable.new
|
|
110
|
+
@owner = nil
|
|
111
|
+
@background = false
|
|
112
|
+
@waiters = 0
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
private
|
|
116
|
+
|
|
117
|
+
# A thread holding the loop can be gone without releasing it, e.g.
|
|
118
|
+
# when killed.
|
|
119
|
+
def free?
|
|
120
|
+
@owner.nil? || !@owner.alive?
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
@@ -8,16 +8,18 @@ module Restify
|
|
|
8
8
|
module Telemetry
|
|
9
9
|
def call(request)
|
|
10
10
|
method = request.method.to_s.upcase
|
|
11
|
-
uri =
|
|
12
|
-
|
|
11
|
+
uri = request.uri
|
|
12
|
+
port = uri.inferred_port
|
|
13
|
+
name = "#{method} #{uri.scheme}://#{uri.host}:#{port}"
|
|
13
14
|
|
|
15
|
+
# Remove `nil` as OTEL spans must not contain any nil attributes
|
|
14
16
|
attributes = {
|
|
15
17
|
'http.request.method' => method,
|
|
16
18
|
'server.address' => uri.host,
|
|
17
|
-
'server.port' =>
|
|
19
|
+
'server.port' => port,
|
|
18
20
|
'url.full' => uri.to_s,
|
|
19
21
|
'url.scheme' => uri.scheme,
|
|
20
|
-
}
|
|
22
|
+
}.compact
|
|
21
23
|
|
|
22
24
|
span = tracer.start_span(name, attributes:, kind: :client)
|
|
23
25
|
OpenTelemetry::Trace.with_span(span) do
|
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
begin
|
|
4
|
+
require 'typhoeus'
|
|
5
|
+
rescue LoadError => e
|
|
6
|
+
raise LoadError.new(
|
|
7
|
+
"Restify::Adapter::Typhoeus requires the `typhoeus` gem, add it to your Gemfile (#{e.message})",
|
|
8
|
+
)
|
|
9
|
+
end
|
|
6
10
|
|
|
7
11
|
module Restify
|
|
8
12
|
module Adapter
|
|
@@ -23,6 +27,14 @@ module Restify
|
|
|
23
27
|
tcp_keepintvl: 5,
|
|
24
28
|
}.freeze
|
|
25
29
|
|
|
30
|
+
# Restify follows relations from URLs in server responses, and
|
|
31
|
+
# libcurl supports far more than HTTP, e.g. `file://` or `scp://`.
|
|
32
|
+
# Therefore only HTTP-like protocols must ever be used, both for
|
|
33
|
+
# the request itself and when following redirects.
|
|
34
|
+
#
|
|
35
|
+
# This is intentionally not configurable.
|
|
36
|
+
PROTOCOLS = %i[http https].freeze
|
|
37
|
+
|
|
26
38
|
# Patch Hydra to restore the correct OpenTelemetry span when
|
|
27
39
|
# adding the request, so that the Ethon instrumentation can
|
|
28
40
|
# properly pick up the context where the Restify request
|
|
@@ -41,8 +53,8 @@ module Restify
|
|
|
41
53
|
end
|
|
42
54
|
end
|
|
43
55
|
|
|
44
|
-
def initialize(sync: false, options: {}, **
|
|
45
|
-
@hydra = ::Typhoeus::Hydra.new(**
|
|
56
|
+
def initialize(sync: false, options: {}, **)
|
|
57
|
+
@hydra = ::Typhoeus::Hydra.new(**)
|
|
46
58
|
@hydra.extend(EasyOverride)
|
|
47
59
|
|
|
48
60
|
@mutex = Mutex.new
|
|
@@ -62,8 +74,11 @@ module Restify
|
|
|
62
74
|
req = convert(request, writer)
|
|
63
75
|
|
|
64
76
|
if sync?
|
|
65
|
-
|
|
66
|
-
|
|
77
|
+
begin
|
|
78
|
+
req.run
|
|
79
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
80
|
+
writer.reject(e)
|
|
81
|
+
end
|
|
67
82
|
else
|
|
68
83
|
debug 'request:add',
|
|
69
84
|
tag: request.object_id,
|
|
@@ -71,7 +86,7 @@ module Restify
|
|
|
71
86
|
url: request.uri,
|
|
72
87
|
timeout: request.timeout
|
|
73
88
|
|
|
74
|
-
@queue <<
|
|
89
|
+
@queue << req
|
|
75
90
|
|
|
76
91
|
thread.run unless thread.status
|
|
77
92
|
end
|
|
@@ -88,33 +103,38 @@ module Restify
|
|
|
88
103
|
body: request.body,
|
|
89
104
|
timeout: request.timeout,
|
|
90
105
|
connecttimeout: request.timeout,
|
|
106
|
+
|
|
107
|
+
# Block accessing and redirecting to non-HTTP protocols:
|
|
108
|
+
protocols: PROTOCOLS,
|
|
109
|
+
redir_protocols: PROTOCOLS,
|
|
91
110
|
).tap do |req|
|
|
92
111
|
req._otel_span = OpenTelemetry::Trace.current_span
|
|
93
112
|
req._restify_writer = writer
|
|
94
113
|
|
|
95
114
|
req.on_complete do |response|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Restify::NetworkError.new(request, response.return_message)
|
|
105
|
-
|
|
106
|
-
|
|
115
|
+
writer.set do
|
|
116
|
+
debug 'request:complete',
|
|
117
|
+
tag: request.object_id,
|
|
118
|
+
status: response.code,
|
|
119
|
+
message: response.return_message,
|
|
120
|
+
timeout: response.timed_out?
|
|
121
|
+
|
|
122
|
+
if response.timed_out? || response.code.zero?
|
|
123
|
+
raise Restify::NetworkError.new(request, response.return_message)
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
convert_back(response, request)
|
|
107
127
|
end
|
|
108
128
|
|
|
109
|
-
# Add all newly queued requests to active hydra, e.g.
|
|
110
|
-
# queued in a completion callback.
|
|
129
|
+
# Add all newly queued requests to active hydra, e.g.
|
|
130
|
+
# requests queued in a completion callback.
|
|
111
131
|
dequeue_all
|
|
112
132
|
end
|
|
113
133
|
end
|
|
114
134
|
end
|
|
115
135
|
|
|
116
136
|
def convert_back(response, request)
|
|
117
|
-
uri = request
|
|
137
|
+
uri = effective_uri(response, request)
|
|
118
138
|
status = response.code
|
|
119
139
|
body = response.body
|
|
120
140
|
headers = convert_headers(response.headers)
|
|
@@ -122,6 +142,11 @@ module Restify
|
|
|
122
142
|
::Restify::Response.new(request, uri, status, headers, body)
|
|
123
143
|
end
|
|
124
144
|
|
|
145
|
+
def effective_uri(response, request)
|
|
146
|
+
url = response.effective_url
|
|
147
|
+
url ? Addressable::URI.parse(url) : request.uri
|
|
148
|
+
end
|
|
149
|
+
|
|
125
150
|
def convert_headers(headers)
|
|
126
151
|
return {} unless headers.respond_to?(:each_pair)
|
|
127
152
|
|
|
@@ -165,7 +190,7 @@ module Restify
|
|
|
165
190
|
runs += 1
|
|
166
191
|
debug 'hydra:completed'
|
|
167
192
|
rescue StandardError => e
|
|
168
|
-
|
|
193
|
+
error(e)
|
|
169
194
|
end
|
|
170
195
|
ensure
|
|
171
196
|
debug 'hydra:exit'
|
data/lib/restify/context.rb
CHANGED
|
@@ -34,9 +34,9 @@ module Restify
|
|
|
34
34
|
self.uri.join uri
|
|
35
35
|
end
|
|
36
36
|
|
|
37
|
-
def inherit(uri, **
|
|
37
|
+
def inherit(uri, **)
|
|
38
38
|
uri ||= self.uri
|
|
39
|
-
Context.new(uri,
|
|
39
|
+
Context.new(uri, **, **options)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
42
|
def process(response)
|
|
@@ -47,16 +47,16 @@ module Restify
|
|
|
47
47
|
processor.new(context, response).resource
|
|
48
48
|
end
|
|
49
49
|
|
|
50
|
-
def request(method, uri, data: nil, headers: {}, **
|
|
50
|
+
def request(method, uri, data: nil, headers: {}, **)
|
|
51
51
|
request = Request.new(
|
|
52
52
|
headers: default_headers.merge(headers),
|
|
53
|
-
|
|
53
|
+
**,
|
|
54
54
|
method:,
|
|
55
55
|
uri: join(uri),
|
|
56
56
|
data:,
|
|
57
57
|
)
|
|
58
58
|
|
|
59
|
-
ret = cache.call(request) {|req| adapter.call(req) }
|
|
59
|
+
ret = cache ? cache.call(request) {|req| adapter.call(req) } : adapter.call(request)
|
|
60
60
|
ret.then do |response|
|
|
61
61
|
raise ResponseError.from_code(response) if response.errored?
|
|
62
62
|
|
data/lib/restify/error.rb
CHANGED
|
@@ -13,6 +13,19 @@ module Restify
|
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
# A {ParseError} is raised when accessing the data of a resource,
|
|
17
|
+
# whose response body could not be parsed, e.g. invalid JSON. The
|
|
18
|
+
# original error is available as {#cause}.
|
|
19
|
+
#
|
|
20
|
+
class ParseError < StandardError
|
|
21
|
+
attr_reader :response
|
|
22
|
+
|
|
23
|
+
def initialize(response, message)
|
|
24
|
+
@response = response
|
|
25
|
+
super("Could not parse response body for `#{response&.uri}': #{message}")
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
16
29
|
# A {ResponseError} is returned on a non-successful
|
|
17
30
|
# response from server. Usually it will either be a
|
|
18
31
|
# {ClientError} or a {ServerError}.
|
data/lib/restify/global.rb
CHANGED
|
@@ -2,47 +2,26 @@
|
|
|
2
2
|
|
|
3
3
|
module Restify
|
|
4
4
|
module Global
|
|
5
|
-
def new(uri, **
|
|
6
|
-
context = resolve_context
|
|
5
|
+
def new(uri, **)
|
|
6
|
+
context = resolve_context(uri, **)
|
|
7
7
|
|
|
8
8
|
Relation.new context, context.uri
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Restify::Adapter::Typhoeus.new
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def adapter=(adapter)
|
|
18
|
-
@adapter = adapter
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def cache
|
|
22
|
-
@cache ||= begin
|
|
23
|
-
require 'active_support'
|
|
24
|
-
require 'active_support/cache'
|
|
25
|
-
Restify::Cache.new store: ActiveSupport::Cache::MemoryStore.new
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def cache=(cache)
|
|
30
|
-
@cache = cache
|
|
31
|
-
end
|
|
11
|
+
attr_writer :adapter
|
|
12
|
+
attr_accessor :cache, :logger
|
|
32
13
|
|
|
33
|
-
def
|
|
34
|
-
::
|
|
14
|
+
def adapter
|
|
15
|
+
@adapter ||= Restify::Adapter::Ethon.new
|
|
35
16
|
end
|
|
36
17
|
|
|
37
|
-
def logger=(logger); end
|
|
38
|
-
|
|
39
18
|
private
|
|
40
19
|
|
|
41
|
-
def resolve_context(uri, **
|
|
20
|
+
def resolve_context(uri, **)
|
|
42
21
|
if uri.is_a? Symbol
|
|
43
|
-
Restify::Registry.fetch(uri).inherit(nil, **
|
|
22
|
+
Restify::Registry.fetch(uri).inherit(nil, **)
|
|
44
23
|
else
|
|
45
|
-
Context.new(uri, **
|
|
24
|
+
Context.new(uri, **)
|
|
46
25
|
end
|
|
47
26
|
end
|
|
48
27
|
end
|
data/lib/restify/logging.rb
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'logging'
|
|
4
|
-
|
|
5
3
|
module Restify
|
|
6
4
|
module Logging
|
|
7
5
|
def logger
|
|
8
|
-
|
|
6
|
+
Restify.logger
|
|
9
7
|
end
|
|
10
8
|
|
|
11
9
|
def debug(message = nil, tag: nil, **kwargs)
|
|
12
|
-
logger
|
|
10
|
+
logger&.debug(_log_name) do
|
|
13
11
|
[
|
|
14
12
|
_log_prefix,
|
|
15
13
|
*Array(tag),
|
|
@@ -19,6 +17,14 @@ module Restify
|
|
|
19
17
|
end
|
|
20
18
|
end
|
|
21
19
|
|
|
20
|
+
def error(exception)
|
|
21
|
+
logger&.error(_log_name) { exception }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def _log_name
|
|
25
|
+
is_a?(Module) ? name : self.class.name
|
|
26
|
+
end
|
|
27
|
+
|
|
22
28
|
def _log_prefix
|
|
23
29
|
nil
|
|
24
30
|
end
|
|
@@ -10,7 +10,19 @@ module Restify
|
|
|
10
10
|
#
|
|
11
11
|
module Parsing
|
|
12
12
|
def load
|
|
13
|
-
|
|
13
|
+
# No data, e.g. when a server sets a content type but sends an
|
|
14
|
+
# empty body.
|
|
15
|
+
return if body.nil? || body.empty?
|
|
16
|
+
|
|
17
|
+
begin
|
|
18
|
+
data = deserialized_body
|
|
19
|
+
rescue StandardError => e
|
|
20
|
+
# Keep the resource, e.g. with relations from headers, but
|
|
21
|
+
# raise on accessing its data.
|
|
22
|
+
return Resource.new(context, response:, error: e)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
parse(data, root: true)
|
|
14
26
|
end
|
|
15
27
|
|
|
16
28
|
def parse(object, root: false)
|
data/lib/restify/promise.rb
CHANGED
|
@@ -2,9 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
module Restify
|
|
4
4
|
class Promise < Concurrent::IVar
|
|
5
|
+
# A driver that can complete this promise in the waiting thread,
|
|
6
|
+
# e.g. an adapter running its event loop. See `#wait`.
|
|
7
|
+
#
|
|
8
|
+
# @api private
|
|
9
|
+
attr_writer :driver
|
|
10
|
+
|
|
5
11
|
def initialize(*dependencies, &task)
|
|
6
12
|
@task = task
|
|
7
13
|
@dependencies = dependencies.flatten
|
|
14
|
+
@driver = nil
|
|
8
15
|
|
|
9
16
|
super(&nil)
|
|
10
17
|
|
|
@@ -19,7 +26,11 @@ module Restify
|
|
|
19
26
|
|
|
20
27
|
execute(t) if pending?
|
|
21
28
|
|
|
22
|
-
|
|
29
|
+
# Let the driver run on the current thread instead of sleeping and
|
|
30
|
+
# switching to another thread if possible. If unsupported, the
|
|
31
|
+
# driver returns false.
|
|
32
|
+
super unless incomplete? && @driver&.drive(self, t)
|
|
33
|
+
|
|
23
34
|
raise t if incomplete?
|
|
24
35
|
|
|
25
36
|
self
|
|
@@ -62,8 +73,9 @@ module Restify
|
|
|
62
73
|
end
|
|
63
74
|
|
|
64
75
|
class << self
|
|
65
|
-
def create
|
|
76
|
+
def create(driver: nil)
|
|
66
77
|
promise = Promise.new
|
|
78
|
+
promise.driver = driver
|
|
67
79
|
yield Writer.new(promise)
|
|
68
80
|
promise
|
|
69
81
|
end
|
|
@@ -93,6 +105,12 @@ module Restify
|
|
|
93
105
|
def reject(reason)
|
|
94
106
|
@promise.send :complete, false, nil, reason
|
|
95
107
|
end
|
|
108
|
+
|
|
109
|
+
def set
|
|
110
|
+
fulfill(yield)
|
|
111
|
+
rescue Exception => e # rubocop:disable Lint/RescueException
|
|
112
|
+
reject(e)
|
|
113
|
+
end
|
|
96
114
|
end
|
|
97
115
|
end
|
|
98
116
|
end
|
data/lib/restify/registry.rb
CHANGED
data/lib/restify/relation.rb
CHANGED
|
@@ -19,20 +19,20 @@ module Restify
|
|
|
19
19
|
@template = Addressable::Template.new(template)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
|
-
def request(method:, params: {}, **
|
|
23
|
-
context.request(method, expand(params), **
|
|
22
|
+
def request(method:, params: {}, **)
|
|
23
|
+
context.request(method, expand(params), **)
|
|
24
24
|
end
|
|
25
25
|
|
|
26
|
-
def get(data = {}, params: {}, **
|
|
27
|
-
request(
|
|
26
|
+
def get(data = {}, params: {}, **)
|
|
27
|
+
request(**, method: :get, params: data.merge(params))
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
def head(data = {}, params: {}, **
|
|
31
|
-
request(
|
|
30
|
+
def head(data = {}, params: {}, **)
|
|
31
|
+
request(**, method: :head, params: data.merge(params))
|
|
32
32
|
end
|
|
33
33
|
|
|
34
|
-
def delete(data = {}, params: {}, **
|
|
35
|
-
request(
|
|
34
|
+
def delete(data = {}, params: {}, **)
|
|
35
|
+
request(**, method: :delete, params: data.merge(params))
|
|
36
36
|
end
|
|
37
37
|
|
|
38
38
|
def post(data = nil, **opts)
|
data/lib/restify/request.rb
CHANGED
|
@@ -11,7 +11,7 @@ module Restify
|
|
|
11
11
|
|
|
12
12
|
# Request URI.
|
|
13
13
|
#
|
|
14
|
-
# @return [
|
|
14
|
+
# @return [Addressable::URI] Request URI.
|
|
15
15
|
#
|
|
16
16
|
attr_reader :uri
|
|
17
17
|
|
|
@@ -30,7 +30,7 @@ module Restify
|
|
|
30
30
|
attr_reader :timeout
|
|
31
31
|
|
|
32
32
|
def initialize(uri:, method: :get, data: nil, timeout: 300, headers: {})
|
|
33
|
-
@uri = uri
|
|
33
|
+
@uri = uri.is_a?(Addressable::URI) ? uri : Addressable::URI.parse(uri)
|
|
34
34
|
@method = method.to_s.downcase
|
|
35
35
|
@data = data
|
|
36
36
|
@timeout = timeout
|
data/lib/restify/resource.rb
CHANGED
|
@@ -6,12 +6,13 @@ module Restify
|
|
|
6
6
|
class Resource < SimpleDelegator
|
|
7
7
|
# @api private
|
|
8
8
|
#
|
|
9
|
-
def initialize(context, response: nil, data: nil, relations: {})
|
|
9
|
+
def initialize(context, response: nil, data: nil, relations: {}, error: nil)
|
|
10
10
|
super(data)
|
|
11
11
|
|
|
12
12
|
@context = context
|
|
13
13
|
@response = response
|
|
14
14
|
@relations = relations
|
|
15
|
+
@error = error
|
|
15
16
|
end
|
|
16
17
|
|
|
17
18
|
# Check if resource has a relation with given name.
|
|
@@ -42,14 +43,31 @@ module Restify
|
|
|
42
43
|
|
|
43
44
|
alias rel relation
|
|
44
45
|
|
|
46
|
+
# @api private
|
|
47
|
+
def __getobj__
|
|
48
|
+
# `Delegator` removes `Kernel#raise`, and the cause can only be
|
|
49
|
+
# set when raising.
|
|
50
|
+
::Kernel.raise ParseError.new(@response, @error.message), cause: @error if @error
|
|
51
|
+
|
|
52
|
+
super
|
|
53
|
+
end
|
|
54
|
+
|
|
45
55
|
# @!method data
|
|
46
56
|
#
|
|
47
57
|
# Return response data. Usually a hash or array.
|
|
48
58
|
#
|
|
49
59
|
# @return [Object] Response data.
|
|
60
|
+
# @raise [ParseError] If the response body could not be parsed.
|
|
50
61
|
#
|
|
51
62
|
alias data __getobj__
|
|
52
63
|
|
|
64
|
+
# @api private
|
|
65
|
+
def respond_to_missing?(name, include_private = false)
|
|
66
|
+
return false if @error
|
|
67
|
+
|
|
68
|
+
super
|
|
69
|
+
end
|
|
70
|
+
|
|
53
71
|
# @!method response
|
|
54
72
|
#
|
|
55
73
|
# Return response if available.
|
|
@@ -95,7 +113,7 @@ module Restify
|
|
|
95
113
|
# @api private
|
|
96
114
|
def inspect
|
|
97
115
|
text = {
|
|
98
|
-
'@data' => data,
|
|
116
|
+
(@error ? '@error' : '@data') => @error || data,
|
|
99
117
|
'@relations' => @relations,
|
|
100
118
|
}.map {|k, v| "#{k}=#{v.inspect}" }.join(' ')
|
|
101
119
|
|