restify 2.1.0 → 3.0.0.rc3

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.
Files changed (222) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +75 -0
  3. data/README.md +30 -5
  4. data/lib/restify/adapter/base.rb +10 -1
  5. data/lib/restify/adapter/ethon/easy.rb +147 -0
  6. data/lib/restify/adapter/ethon/event_loop.rb +255 -0
  7. data/lib/restify/adapter/ethon/options.rb +81 -0
  8. data/lib/restify/adapter/ethon/pool.rb +43 -0
  9. data/lib/restify/adapter/ethon.rb +211 -0
  10. data/lib/restify/adapter/loop_lock.rb +124 -0
  11. data/lib/restify/adapter/telemetry.rb +7 -5
  12. data/lib/restify/adapter/typhoeus.rb +52 -23
  13. data/lib/restify/context.rb +16 -6
  14. data/lib/restify/error.rb +13 -0
  15. data/lib/restify/global.rb +9 -30
  16. data/lib/restify/logging.rb +10 -4
  17. data/lib/restify/processors/base/parsing.rb +43 -26
  18. data/lib/restify/promise.rb +194 -42
  19. data/lib/restify/registry.rb +2 -2
  20. data/lib/restify/relation.rb +27 -13
  21. data/lib/restify/request.rb +2 -2
  22. data/lib/restify/resource.rb +20 -2
  23. data/lib/restify/response.rb +39 -3
  24. data/lib/restify/timeout.rb +23 -34
  25. data/lib/restify/version.rb +3 -3
  26. data/lib/restify/webmock.rb +126 -0
  27. data/lib/restify.rb +5 -2
  28. data/spec/restify/adapter/ethon/easy_spec.rb +111 -0
  29. data/spec/restify/adapter/ethon/event_loop_spec.rb +96 -0
  30. data/spec/restify/adapter/ethon/options_spec.rb +104 -0
  31. data/spec/restify/adapter/ethon/pool_spec.rb +81 -0
  32. data/spec/restify/adapter/ethon_spec.rb +307 -0
  33. data/spec/restify/adapter/loop_lock_spec.rb +144 -0
  34. data/spec/restify/adapter/telemetry_spec.rb +61 -0
  35. data/spec/restify/adapter/typhoeus_spec.rb +26 -0
  36. data/spec/restify/cache_spec.rb +1 -3
  37. data/spec/restify/context_spec.rb +69 -0
  38. data/spec/restify/features/opentelemetry_spec.rb +2 -0
  39. data/spec/restify/features/protocols_spec.rb +28 -0
  40. data/spec/restify/features/redirects_spec.rb +45 -0
  41. data/spec/restify/features/request_errors_spec.rb +1 -1
  42. data/spec/restify/features/response_bodies_spec.rb +45 -0
  43. data/spec/restify/features/response_encoding_spec.rb +82 -0
  44. data/spec/restify/features/response_errors_spec.rb +22 -1
  45. data/spec/restify/features/webmock_spec.rb +92 -1
  46. data/spec/restify/global_spec.rb +78 -10
  47. data/spec/restify/processors/json_spec.rb +103 -0
  48. data/spec/restify/processors/msgpack_spec.rb +36 -0
  49. data/spec/restify/promise_spec.rb +288 -9
  50. data/spec/restify/relation_spec.rb +25 -6
  51. data/spec/restify/request_spec.rb +26 -0
  52. data/spec/restify/timeout_spec.rb +43 -33
  53. data/spec/spec_helper.rb +10 -6
  54. data/spec/support/stub_server.rb +4 -4
  55. metadata +32 -221
  56. data/vendor/bundle/ruby/4.0.0/bundler/gems/my-rubocop-2b861962124a/LICENSE +0 -21
  57. data/vendor/bundle/ruby/4.0.0/bundler/gems/my-rubocop-2b861962124a/README.md +0 -23
  58. data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/CHANGELOG.md +0 -561
  59. data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/MIT-LICENSE +0 -20
  60. data/vendor/bundle/ruby/4.0.0/gems/activesupport-8.1.3/README.rdoc +0 -40
  61. data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/CHANGELOG.md +0 -326
  62. data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/LICENSE.txt +0 -202
  63. data/vendor/bundle/ruby/4.0.0/gems/addressable-2.9.0/README.md +0 -121
  64. data/vendor/bundle/ruby/4.0.0/gems/ast-2.4.3/LICENSE.MIT +0 -20
  65. data/vendor/bundle/ruby/4.0.0/gems/ast-2.4.3/README.YARD.md +0 -12
  66. data/vendor/bundle/ruby/4.0.0/gems/base64-0.3.0/README.md +0 -48
  67. data/vendor/bundle/ruby/4.0.0/gems/bigdecimal-4.1.2/LICENSE +0 -56
  68. data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/CHANGELOG.md +0 -615
  69. data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/LICENSE.txt +0 -21
  70. data/vendor/bundle/ruby/4.0.0/gems/concurrent-ruby-1.3.7/README.md +0 -409
  71. data/vendor/bundle/ruby/4.0.0/gems/connection_pool-3.0.2/LICENSE +0 -20
  72. data/vendor/bundle/ruby/4.0.0/gems/connection_pool-3.0.2/README.md +0 -182
  73. data/vendor/bundle/ruby/4.0.0/gems/crack-1.0.1/LICENSE +0 -20
  74. data/vendor/bundle/ruby/4.0.0/gems/crack-1.0.1/README.md +0 -43
  75. data/vendor/bundle/ruby/4.0.0/gems/diff-lcs-1.6.2/CHANGELOG.md +0 -518
  76. data/vendor/bundle/ruby/4.0.0/gems/diff-lcs-1.6.2/README.md +0 -92
  77. data/vendor/bundle/ruby/4.0.0/gems/docile-1.4.1/LICENSE +0 -21
  78. data/vendor/bundle/ruby/4.0.0/gems/docile-1.4.1/README.md +0 -409
  79. data/vendor/bundle/ruby/4.0.0/gems/drb-2.2.3/LICENSE.txt +0 -22
  80. data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/CHANGELOG.md +0 -417
  81. data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/LICENSE +0 -20
  82. data/vendor/bundle/ruby/4.0.0/gems/ethon-0.18.0/README.md +0 -118
  83. data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/CHANGELOG.md +0 -507
  84. data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/LICENSE +0 -24
  85. data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/LICENSE.SPECS +0 -22
  86. data/vendor/bundle/ruby/4.0.0/gems/ffi-1.17.4-x86_64-linux-gnu/README.md +0 -138
  87. data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/LICENSE +0 -19
  88. data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/README.md +0 -323
  89. data/vendor/bundle/ruby/4.0.0/gems/hashdiff-1.2.1/changelog.md +0 -127
  90. data/vendor/bundle/ruby/4.0.0/gems/hitimes-3.2.0/LICENSE.txt +0 -16
  91. data/vendor/bundle/ruby/4.0.0/gems/hitimes-3.2.0/README.md +0 -187
  92. data/vendor/bundle/ruby/4.0.0/gems/i18n-1.15.2/MIT-LICENSE +0 -20
  93. data/vendor/bundle/ruby/4.0.0/gems/i18n-1.15.2/README.md +0 -139
  94. data/vendor/bundle/ruby/4.0.0/gems/json-2.19.9/README.md +0 -310
  95. data/vendor/bundle/ruby/4.0.0/gems/language_server-protocol-3.17.0.5/LICENSE.txt +0 -21
  96. data/vendor/bundle/ruby/4.0.0/gems/language_server-protocol-3.17.0.5/README.md +0 -88
  97. data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/CHANGELOG.md +0 -15
  98. data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/LICENSE.txt +0 -21
  99. data/vendor/bundle/ruby/4.0.0/gems/lint_roller-1.1.0/README.md +0 -173
  100. data/vendor/bundle/ruby/4.0.0/gems/little-plugger-1.1.4/README.rdoc +0 -53
  101. data/vendor/bundle/ruby/4.0.0/gems/logger-1.7.0/README.md +0 -104
  102. data/vendor/bundle/ruby/4.0.0/gems/logging-2.4.0/LICENSE +0 -22
  103. data/vendor/bundle/ruby/4.0.0/gems/logging-2.4.0/README.md +0 -140
  104. data/vendor/bundle/ruby/4.0.0/gems/minitest-6.0.6/README.rdoc +0 -763
  105. data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/ChangeLog +0 -383
  106. data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/LICENSE +0 -177
  107. data/vendor/bundle/ruby/4.0.0/gems/msgpack-1.8.3/README.md +0 -302
  108. data/vendor/bundle/ruby/4.0.0/gems/multi_json-1.21.1/LICENSE.md +0 -20
  109. data/vendor/bundle/ruby/4.0.0/gems/multi_json-1.21.1/README.md +0 -281
  110. data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/ext/libev/LICENSE +0 -37
  111. data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/ext/libev/README +0 -59
  112. data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/license.md +0 -80
  113. data/vendor/bundle/ruby/4.0.0/gems/nio4r-2.7.5/readme.md +0 -91
  114. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/CHANGELOG.md +0 -219
  115. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/LICENSE +0 -201
  116. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-api-1.10.0/README.md +0 -68
  117. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/CHANGELOG.md +0 -110
  118. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/LICENSE +0 -201
  119. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-common-0.25.0/README.md +0 -62
  120. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/CHANGELOG.md +0 -97
  121. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/LICENSE +0 -201
  122. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-base-0.26.1/README.md +0 -155
  123. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/CHANGELOG.md +0 -192
  124. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/LICENSE +0 -201
  125. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-instrumentation-ethon-0.29.0/README.md +0 -66
  126. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/CHANGELOG.md +0 -31
  127. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/LICENSE +0 -201
  128. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-registry-0.6.0/README.md +0 -40
  129. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/CHANGELOG.md +0 -302
  130. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/LICENSE +0 -201
  131. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-sdk-1.12.0/README.md +0 -101
  132. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/CHANGELOG.md +0 -65
  133. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/LICENSE +0 -201
  134. data/vendor/bundle/ruby/4.0.0/gems/opentelemetry-semantic_conventions-1.41.0/README.md +0 -115
  135. data/vendor/bundle/ruby/4.0.0/gems/parallel-2.1.0/MIT-LICENSE.txt +0 -20
  136. data/vendor/bundle/ruby/4.0.0/gems/parser-3.3.11.1/LICENSE.txt +0 -26
  137. data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/CHANGELOG.md +0 -786
  138. data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/LICENSE.md +0 -7
  139. data/vendor/bundle/ruby/4.0.0/gems/prism-1.9.0/README.md +0 -143
  140. data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/CHANGELOG.md +0 -649
  141. data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/LICENSE.txt +0 -22
  142. data/vendor/bundle/ruby/4.0.0/gems/public_suffix-7.0.5/README.md +0 -231
  143. data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/LICENSE +0 -29
  144. data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/README.md +0 -484
  145. data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/docs/jungle/README.md +0 -9
  146. data/vendor/bundle/ruby/4.0.0/gems/puma-8.0.2/docs/jungle/rc.d/README.md +0 -74
  147. data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/ChangeLog +0 -846
  148. data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/README.ja.rdoc +0 -58
  149. data/vendor/bundle/ruby/4.0.0/gems/racc-1.8.1/README.rdoc +0 -60
  150. data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/CHANGELOG.md +0 -1346
  151. data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/MIT-LICENSE +0 -20
  152. data/vendor/bundle/ruby/4.0.0/gems/rack-3.2.6/README.md +0 -384
  153. data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/Changelog.md +0 -101
  154. data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/LICENSE +0 -20
  155. data/vendor/bundle/ruby/4.0.0/gems/rainbow-3.1.1/README.markdown +0 -227
  156. data/vendor/bundle/ruby/4.0.0/gems/rake-13.4.2/MIT-LICENSE +0 -21
  157. data/vendor/bundle/ruby/4.0.0/gems/rake-13.4.2/README.rdoc +0 -155
  158. data/vendor/bundle/ruby/4.0.0/gems/rake-release-1.4.0/LICENSE +0 -21
  159. data/vendor/bundle/ruby/4.0.0/gems/rake-release-1.4.0/README.md +0 -107
  160. data/vendor/bundle/ruby/4.0.0/gems/regexp_parser-2.12.0/LICENSE +0 -22
  161. data/vendor/bundle/ruby/4.0.0/gems/rexml-3.4.4/LICENSE.txt +0 -22
  162. data/vendor/bundle/ruby/4.0.0/gems/rexml-3.4.4/README.md +0 -57
  163. data/vendor/bundle/ruby/4.0.0/gems/rspec-3.13.2/LICENSE.md +0 -27
  164. data/vendor/bundle/ruby/4.0.0/gems/rspec-3.13.2/README.md +0 -47
  165. data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/Changelog.md +0 -2447
  166. data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/LICENSE.md +0 -26
  167. data/vendor/bundle/ruby/4.0.0/gems/rspec-core-3.13.6/README.md +0 -389
  168. data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/Changelog.md +0 -1366
  169. data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/LICENSE.md +0 -25
  170. data/vendor/bundle/ruby/4.0.0/gems/rspec-expectations-3.13.5/README.md +0 -326
  171. data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/Changelog.md +0 -1351
  172. data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/LICENSE.md +0 -25
  173. data/vendor/bundle/ruby/4.0.0/gems/rspec-mocks-3.13.8/README.md +0 -465
  174. data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/Changelog.md +0 -444
  175. data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/LICENSE.md +0 -23
  176. data/vendor/bundle/ruby/4.0.0/gems/rspec-support-3.13.7/README.md +0 -40
  177. data/vendor/bundle/ruby/4.0.0/gems/rubocop-1.88.0/LICENSE.txt +0 -20
  178. data/vendor/bundle/ruby/4.0.0/gems/rubocop-1.88.0/README.md +0 -255
  179. data/vendor/bundle/ruby/4.0.0/gems/rubocop-ast-1.49.1/LICENSE.txt +0 -20
  180. data/vendor/bundle/ruby/4.0.0/gems/rubocop-ast-1.49.1/README.md +0 -54
  181. data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/CHANGELOG.md +0 -116
  182. data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/MIT-LICENSE.md +0 -21
  183. data/vendor/bundle/ruby/4.0.0/gems/rubocop-capybara-2.23.0/README.md +0 -91
  184. data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/CHANGELOG.md +0 -135
  185. data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/MIT-LICENSE.md +0 -21
  186. data/vendor/bundle/ruby/4.0.0/gems/rubocop-factory_bot-2.28.0/README.md +0 -91
  187. data/vendor/bundle/ruby/4.0.0/gems/rubocop-performance-1.26.1/LICENSE.txt +0 -20
  188. data/vendor/bundle/ruby/4.0.0/gems/rubocop-performance-1.26.1/README.md +0 -100
  189. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/CHANGELOG.md +0 -1136
  190. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/MIT-LICENSE.md +0 -21
  191. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec-3.10.2/README.md +0 -112
  192. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/CHANGELOG.md +0 -98
  193. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/MIT-LICENSE.md +0 -21
  194. data/vendor/bundle/ruby/4.0.0/gems/rubocop-rspec_rails-2.32.0/README.md +0 -93
  195. data/vendor/bundle/ruby/4.0.0/gems/ruby-progressbar-1.13.0/LICENSE.txt +0 -19
  196. data/vendor/bundle/ruby/4.0.0/gems/ruby-progressbar-1.13.0/README.md +0 -131
  197. data/vendor/bundle/ruby/4.0.0/gems/securerandom-0.4.1/README.md +0 -72
  198. data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/CHANGELOG.md +0 -191
  199. data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/LICENSE +0 -20
  200. data/vendor/bundle/ruby/4.0.0/gems/simplecov-0.22.0/README.md +0 -974
  201. data/vendor/bundle/ruby/4.0.0/gems/simplecov-cobertura-3.2.0/LICENSE +0 -202
  202. data/vendor/bundle/ruby/4.0.0/gems/simplecov-cobertura-3.2.0/README.md +0 -65
  203. data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/CHANGELOG.md +0 -114
  204. data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/LICENSE +0 -20
  205. data/vendor/bundle/ruby/4.0.0/gems/simplecov-html-0.13.2/README.md +0 -30
  206. data/vendor/bundle/ruby/4.0.0/gems/simplecov_json_formatter-0.1.4/CHANGELOG.md +0 -13
  207. data/vendor/bundle/ruby/4.0.0/gems/simplecov_json_formatter-0.1.4/README.md +0 -29
  208. data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/CHANGELOG.md +0 -465
  209. data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/LICENSE +0 -22
  210. data/vendor/bundle/ruby/4.0.0/gems/typhoeus-1.6.0/README.md +0 -588
  211. data/vendor/bundle/ruby/4.0.0/gems/tzinfo-2.0.6/LICENSE +0 -19
  212. data/vendor/bundle/ruby/4.0.0/gems/tzinfo-2.0.6/README.md +0 -406
  213. data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/CHANGELOG.md +0 -299
  214. data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/MIT-LICENSE.txt +0 -22
  215. data/vendor/bundle/ruby/4.0.0/gems/unicode-display_width-3.2.0/README.md +0 -194
  216. data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/CHANGELOG.md +0 -202
  217. data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/MIT-LICENSE.txt +0 -20
  218. data/vendor/bundle/ruby/4.0.0/gems/unicode-emoji-4.2.0/README.md +0 -205
  219. data/vendor/bundle/ruby/4.0.0/gems/uri-1.1.1/README.md +0 -55
  220. data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/CHANGELOG.md +0 -2148
  221. data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/LICENSE +0 -20
  222. data/vendor/bundle/ruby/4.0.0/gems/webmock-3.26.2/README.md +0 -1229
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Restify do
6
+ subject(:resource) { Restify.new('http://localhost:9292/old/resource').get.value! }
7
+
8
+ before do
9
+ stub_request(:get, 'http://stubserver/old/resource')
10
+ .to_return do
11
+ <<~HTTP
12
+ HTTP/1.1 302 Found
13
+ Location: http://localhost:9292/new/resource
14
+
15
+ HTTP
16
+ end
17
+
18
+ stub_request(:get, 'http://stubserver/new/resource')
19
+ .to_return do
20
+ <<~HTTP
21
+ HTTP/1.1 200 OK
22
+ Content-Type: application/json
23
+
24
+ {"name":"John Smith","sibling_url":"./sibling"}
25
+ HTTP
26
+ end
27
+ end
28
+
29
+ describe 'following redirects' do
30
+ it 'returns the redirected resource' do
31
+ expect(resource['name']).to eq 'John Smith'
32
+ expect(resource.response.code).to eq 200
33
+ end
34
+
35
+ it 'exposes the effective URI on the response' do
36
+ expect(resource.response.uri.to_s)
37
+ .to eq 'http://localhost:9292/new/resource'
38
+ end
39
+
40
+ it 'resolves relative relations against the effective URI' do
41
+ expect(resource.rel(:sibling).expand({}).to_s)
42
+ .to eq 'http://localhost:9292/new/sibling'
43
+ end
44
+ end
45
+ end
@@ -2,7 +2,7 @@
2
2
 
3
3
  require 'spec_helper'
4
4
 
5
- describe Restify, adapter: 'Restify::Adapter::Typhoeus' do
5
+ describe Restify do
6
6
  before do
7
7
  stub_request(:get, 'http://stubserver/base').to_timeout
8
8
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Restify do
6
+ subject(:resource) { Restify.new('http://localhost:9292/base').get.value! }
7
+
8
+ before do
9
+ stub_request(:get, 'http://stubserver/base')
10
+ .to_return(
11
+ status: 200,
12
+ headers: {
13
+ 'Content-Type' => 'application/json',
14
+ 'Link' => '<http://localhost:9292/other>; rel="other"',
15
+ },
16
+ body:,
17
+ )
18
+ end
19
+
20
+ describe 'Response bodies' do
21
+ # #31: A content type is set, but the body is empty.
22
+ context 'when empty' do
23
+ let(:body) { '' }
24
+
25
+ it 'returns a resource without data' do
26
+ expect(resource.data).to be_nil
27
+ expect(resource).to have_relation :other
28
+ end
29
+ end
30
+
31
+ context 'when invalid' do
32
+ let(:body) { '{"name": ' }
33
+
34
+ it 'returns a resource with relations from headers' do
35
+ expect(resource).to have_relation :other
36
+ end
37
+
38
+ it 'raises on accessing data' do
39
+ expect { resource.data }.to raise_error(Restify::ParseError, /Could not parse response body/) do |error|
40
+ expect(error.cause).to be_a JSON::ParserError
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,82 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe Restify do
6
+ describe 'Response body encoding' do
7
+ subject(:response) { Restify.new('http://localhost:9292/base').get.value!.response }
8
+
9
+ let(:text) { 'Grüße, Ærø – 日本' }
10
+
11
+ before do
12
+ stub_request(:get, 'http://stubserver/base').to_return(
13
+ status: 200,
14
+ headers: {'Content-Type' => content_type},
15
+ body: body,
16
+ )
17
+ end
18
+
19
+ context 'with an UTF-8 charset' do
20
+ let(:content_type) { 'text/plain; charset=UTF-8' }
21
+ let(:body) { text.encode(Encoding::UTF_8) }
22
+
23
+ it 'returns the body in the given encoding' do
24
+ expect(response.body.encoding).to eq Encoding::UTF_8
25
+ expect(response.body).to eq text
26
+ end
27
+ end
28
+
29
+ context 'with an ISO-8859-1 charset' do
30
+ let(:content_type) { 'text/plain; charset=ISO-8859-1' }
31
+ let(:text) { 'Grüße, Ærø' }
32
+ let(:body) { text.encode(Encoding::ISO_8859_1) }
33
+
34
+ it 'returns the body in the given encoding' do
35
+ expect(response.body.encoding).to eq Encoding::ISO_8859_1
36
+ expect(response.body).to eq text.encode(Encoding::ISO_8859_1)
37
+ expect(response.body.encode(Encoding::UTF_8)).to eq text
38
+ end
39
+ end
40
+
41
+ context 'with a quoted charset' do
42
+ let(:content_type) { 'text/plain; charset="utf-8"' }
43
+ let(:body) { text.encode(Encoding::UTF_8) }
44
+
45
+ it 'returns the body in the given encoding' do
46
+ expect(response.body.encoding).to eq Encoding::UTF_8
47
+ expect(response.body).to eq text
48
+ end
49
+ end
50
+
51
+ context 'with an unknown charset' do
52
+ let(:content_type) { 'text/plain; charset=nonsense' }
53
+ let(:body) { text.encode(Encoding::UTF_8) }
54
+
55
+ it 'returns the body as binary' do
56
+ expect(response.body.encoding).to eq Encoding::BINARY
57
+ expect(response.body.b).to eq text.b
58
+ end
59
+ end
60
+
61
+ context 'without a charset' do
62
+ let(:content_type) { 'text/plain' }
63
+ let(:body) { text.encode(Encoding::UTF_8) }
64
+
65
+ it 'returns the body as binary' do
66
+ expect(response.body.encoding).to eq Encoding::BINARY
67
+ expect(response.body.b).to eq text.b
68
+ end
69
+ end
70
+
71
+ context 'with a JSON body' do
72
+ let(:content_type) { 'application/json; charset=ISO-8859-1' }
73
+ let(:text) { 'Grüße, Ærø' }
74
+ let(:body) { %("#{text}").encode(Encoding::ISO_8859_1) }
75
+
76
+ it 'decodes the body using the given encoding' do
77
+ expect(response.body.encoding).to eq Encoding::ISO_8859_1
78
+ expect(response.decoded_body).to eq text
79
+ end
80
+ end
81
+ end
82
+ end
@@ -5,11 +5,12 @@ require 'spec_helper'
5
5
  describe Restify do
6
6
  before do
7
7
  stub_request(:get, 'http://stubserver/base')
8
- .to_return(status: http_status, headers:)
8
+ .to_return(status: http_status, headers:, body:)
9
9
  end
10
10
 
11
11
  let(:http_status) { '200 OK' }
12
12
  let(:headers) { {} }
13
+ let(:body) { '' }
13
14
 
14
15
  describe 'Error handling' do
15
16
  subject(:request) { Restify.new('http://localhost:9292/base').get.value! }
@@ -20,6 +21,26 @@ describe Restify do
20
21
  it 'throws a BadRequest exception' do
21
22
  expect { request }.to raise_error Restify::BadRequest
22
23
  end
24
+
25
+ # #31: Rails sets a JSON content type even for empty bodies.
26
+ context 'with a JSON content type and an empty body' do
27
+ let(:headers) { {'Content-Type' => 'application/json'} }
28
+
29
+ it 'throws a BadRequest exception' do
30
+ expect { request }.to raise_error Restify::BadRequest
31
+ end
32
+ end
33
+
34
+ context 'with an invalid JSON body' do
35
+ let(:headers) { {'Content-Type' => 'application/json'} }
36
+ let(:body) { '{"errors": ' }
37
+
38
+ it 'throws a BadRequest exception with the raw body as errors' do
39
+ expect { request }.to raise_error(Restify::BadRequest) do |error|
40
+ expect(error.errors).to eq '{"errors": '
41
+ end
42
+ end
43
+ end
23
44
  end
24
45
 
25
46
  context 'for 401 status codes' do
@@ -4,11 +4,13 @@ require 'spec_helper'
4
4
 
5
5
  describe Restify do
6
6
  before do
7
- WebMock.enable!
7
+ WebMock.enable!(except: %i[typhoeus])
8
8
  end
9
9
 
10
10
  after do
11
11
  WebMock.disable!(except: %i[net_http])
12
+ WebMock.disable_net_connect!
13
+ WebMock::CallbackRegistry.reset
12
14
  end
13
15
 
14
16
  describe 'WebMock' do
@@ -23,5 +25,94 @@ describe Restify do
23
25
  it 'raises error for not stubbed requests' do
24
26
  expect { resource }.to raise_error WebMock::NetConnectNotAllowedError
25
27
  end
28
+
29
+ it 'returns stubbed responses' do
30
+ stub_request(:get, 'http://www.example.com/base')
31
+ .to_return(
32
+ headers: {'Content-Type' => 'application/json', 'X-Custom' => 'yes'},
33
+ body: '{"name": "restify", "self_url": "http://www.example.com/self"}',
34
+ )
35
+
36
+ expect(resource['name']).to eq 'restify'
37
+ expect(resource).to have_relation :self
38
+ expect(resource.response.headers).to include('X_CUSTOM' => 'yes')
39
+ end
40
+
41
+ it 'records requests' do
42
+ stub_request(:post, 'http://www.example.com/base')
43
+
44
+ Restify.new('http://www.example.com/base').post({name: 'restify'}).value!
45
+
46
+ expect(
47
+ a_request(:post, 'http://www.example.com/base')
48
+ .with(body: {name: 'restify'}.to_json, headers: {'Content-Type' => 'application/json'}),
49
+ ).to have_been_made.once
50
+ end
51
+
52
+ it 'raises network errors on stubbed timeouts' do
53
+ stub_request(:get, 'http://www.example.com/base').to_timeout
54
+
55
+ expect { resource }.to raise_error Restify::NetworkError, /timeout/i
56
+ end
57
+
58
+ it 'raises stubbed errors' do
59
+ stub_request(:get, 'http://www.example.com/base').to_raise(Errno::ECONNREFUSED)
60
+
61
+ expect { resource }.to raise_error Errno::ECONNREFUSED
62
+ end
63
+
64
+ it 'creates a span for stubbed requests' do
65
+ stub_request(:get, 'http://www.example.com/base')
66
+
67
+ resource
68
+
69
+ expect(OTLE_EXPORTER.finished_spans.map {|span| span.instrumentation_scope.name }).to eq ['restify']
70
+ end
71
+
72
+ context 'when disabled' do
73
+ it 'does not intercept requests' do
74
+ stub_request(:get, 'http://localhost:9292/echo').to_return(body: 'stubbed')
75
+ WebMock.disable!(except: %i[net_http])
76
+
77
+ expect(Restify.new('http://localhost:9292/echo').get.value!.response.body).not_to eq 'stubbed'
78
+ end
79
+ end
80
+
81
+ # Like WebMock does for other libcurl-based libraries: Redirects are
82
+ # returned as they are.
83
+ it 'returns stubbed redirects as they are' do
84
+ stub_request(:get, 'http://www.example.com/base')
85
+ .to_return(status: 302, headers: {'Location' => '/other'})
86
+
87
+ expect(resource.response.code).to eq 302
88
+ expect(resource.response.headers).to include('LOCATION' => '/other')
89
+ expect(a_request(:get, 'http://www.example.com/other')).not_to have_been_made
90
+ end
91
+
92
+ context 'with net connect allowed' do
93
+ before { WebMock.allow_net_connect! }
94
+
95
+ it 'passes requests on to the adapter' do
96
+ expect(Restify.new('http://localhost:9292/echo').get.value!.data).to include('REQUEST_METHOD' => 'GET')
97
+ end
98
+
99
+ it 'invokes callbacks for real requests once' do
100
+ responses = Queue.new
101
+ WebMock.after_request(real_requests_only: true) do |signature, response|
102
+ responses << [signature.uri.to_s, response.status[0]]
103
+ end
104
+
105
+ Restify.new('http://localhost:9292/echo').get.value!
106
+
107
+ expect(responses.pop(timeout: 1)).to eq ['http://localhost:9292/echo', 200]
108
+ expect(responses).to be_empty
109
+ end
110
+
111
+ it 'records real requests once' do
112
+ Restify.new('http://localhost:9292/echo').get.value!
113
+
114
+ expect(a_request(:get, 'http://localhost:9292/echo')).to have_been_made.once
115
+ end
116
+ end
26
117
  end
27
118
  end
@@ -42,16 +42,32 @@ describe Restify::Global do
42
42
  describe '#adapter' do
43
43
  subject(:adapter) { global.adapter }
44
44
 
45
- it 'defaults to Typhoeus adapter' do
46
- expect(adapter).to be_a Restify::Adapter::Typhoeus
45
+ around do |example|
46
+ Restify.adapter.tap do |configured|
47
+ Restify.adapter = nil
48
+ example.run
49
+ ensure
50
+ Restify.adapter = configured
51
+ end
52
+ end
53
+
54
+ it 'defaults to Ethon adapter' do
55
+ expect(adapter).to be_a Restify::Adapter::Ethon
47
56
  end
48
57
  end
49
58
 
50
59
  describe '#adapter=' do
51
60
  let(:stub) { Object.new }
52
61
 
53
- # Ensure to reset adapter after these specs!
54
- after { Restify.adapter = nil }
62
+ # Ensure to restore the configured adapter after these specs!
63
+ around do |example|
64
+ Restify.adapter.tap do |configured|
65
+ Restify.adapter = nil
66
+ example.run
67
+ ensure
68
+ Restify.adapter = configured
69
+ end
70
+ end
55
71
 
56
72
  it 'sets a new adapter' do
57
73
  global.adapter = stub
@@ -62,8 +78,8 @@ describe Restify::Global do
62
78
  describe '#cache' do
63
79
  subject(:cache) { global.cache }
64
80
 
65
- it 'defaults to Typhoeus adapter' do
66
- expect(cache).to be_a Restify::Cache
81
+ it 'is not set by default' do
82
+ expect(cache).to be_nil
67
83
  end
68
84
  end
69
85
 
@@ -73,7 +89,7 @@ describe Restify::Global do
73
89
  # Ensure to reset cache after these specs!
74
90
  after { Restify.cache = nil }
75
91
 
76
- it 'sets a new adapter' do
92
+ it 'sets a new cache' do
77
93
  global.cache = stub
78
94
  expect(global.cache).to be stub
79
95
  end
@@ -82,9 +98,61 @@ describe Restify::Global do
82
98
  describe '#logger' do
83
99
  subject(:logger) { global.logger }
84
100
 
85
- it 'returns Restify root logger' do
86
- expect(logger).to be_a Logging::Logger
87
- expect(logger).to eq Logging.logger[Restify]
101
+ around do |example|
102
+ global.logger.tap do |configured|
103
+ global.logger = nil
104
+ example.run
105
+ ensure
106
+ global.logger = configured
107
+ end
108
+ end
109
+
110
+ it 'is not set by default' do
111
+ expect(logger).to be_nil
112
+ end
113
+
114
+ it 'does not log anything without a logger' do
115
+ loggable = Class.new { include Restify::Logging }.new
116
+
117
+ expect { loggable.debug('message') }.not_to output.to_stdout_from_any_process
118
+ expect { loggable.error(RuntimeError.new('kaboom')) }.not_to output.to_stderr_from_any_process
119
+ end
120
+ end
121
+
122
+ describe '#logger=' do
123
+ let(:configured) { Logger.new(nil) }
124
+
125
+ around do |example|
126
+ global.logger.tap do |previous|
127
+ example.run
128
+ ensure
129
+ global.logger = previous
130
+ end
131
+ end
132
+
133
+ it 'sets the logger' do
134
+ global.logger = configured
135
+
136
+ expect(global.logger).to be configured
137
+ end
138
+
139
+ it 'is used for messages from Restify' do
140
+ output = StringIO.new
141
+ global.logger = Logger.new(output, level: :debug)
142
+
143
+ Class.new { include Restify::Logging }.new.debug('message', key: 'value')
144
+
145
+ expect(output.string).to include 'message key=value'
146
+ end
147
+
148
+ it 'is used for errors from Restify' do
149
+ output = StringIO.new
150
+ global.logger = Logger.new(output)
151
+
152
+ stub_const('Loggable', Class.new { include Restify::Logging })
153
+ Loggable.new.error(RuntimeError.new('kaboom'))
154
+
155
+ expect(output.string).to include 'ERROR -- Loggable: kaboom (RuntimeError)'
88
156
  end
89
157
  end
90
158
  end
@@ -31,6 +31,42 @@ describe Restify::Processors::Json do
31
31
 
32
32
  before { allow(response).to receive(:body).and_return(body) }
33
33
 
34
+ describe 'empty body' do
35
+ let(:body) { '' }
36
+
37
+ it { is_expected.to be_a Restify::Resource }
38
+ it { expect(resource.data).to be_nil }
39
+ end
40
+
41
+ describe 'invalid body' do
42
+ let(:body) { '{"json": ' }
43
+
44
+ before do
45
+ allow(response).to receive_messages(
46
+ uri: Addressable::URI.parse('http://test.host/'),
47
+ links: Restify::Link.parse('<http://test.host/other>; rel="other"'),
48
+ )
49
+ end
50
+
51
+ it { is_expected.to be_a Restify::Resource }
52
+ it { is_expected.to have_relation :other }
53
+ it { expect(resource.response).to be response }
54
+
55
+ it 'raises on accessing data' do
56
+ expect { resource.data }.to raise_error(Restify::ParseError) do |error|
57
+ expect(error.response).to be response
58
+ expect(error.cause).to be_a JSON::ParserError
59
+ end
60
+ end
61
+
62
+ it 'raises on accessing delegated data' do
63
+ expect { resource['json'] }.to raise_error Restify::ParseError
64
+ end
65
+
66
+ it { is_expected.not_to respond_to :each }
67
+ it { expect(resource.inspect).to include '@error=' }
68
+ end
69
+
34
70
  describe 'parsing' do
35
71
  context 'single object' do
36
72
  let(:body) do
@@ -60,6 +96,21 @@ describe Restify::Processors::Json do
60
96
  it { expect(resource.relation(:search)).to eq 'https://google.com{?q}' }
61
97
  end
62
98
 
99
+ context 'relation fields with relative references' do
100
+ let(:context) { Restify::Context.new('http://test.host/users/42') }
101
+ let(:body) do
102
+ <<-JSON
103
+ {"items_url": "items", "status_url": "none"}
104
+ JSON
105
+ end
106
+
107
+ it 'resolves them against the context URI' do
108
+ expect(resource.relation(:items).expand({}).to_s).to eq 'http://test.host/users/items'
109
+ end
110
+
111
+ it { is_expected.to have_relation :status }
112
+ end
113
+
63
114
  context 'object with implicit self relation' do
64
115
  let(:body) do
65
116
  <<-JSON
@@ -70,6 +121,58 @@ describe Restify::Processors::Json do
70
121
  it { expect(resource.relation(:self)).to eq '/self' }
71
122
  end
72
123
 
124
+ context 'relation fields in any case' do
125
+ let(:body) do
126
+ <<-JSON
127
+ {"Search_URL": "/search", "URL": "/self"}
128
+ JSON
129
+ end
130
+
131
+ it { expect(resource.relation(:search)).to eq '/search' }
132
+ it { expect(resource.relation(:self)).to eq '/self' }
133
+ end
134
+
135
+ context 'several fields for the same relation' do
136
+ let(:body) do
137
+ <<-JSON
138
+ {"url": "/first", "self_url": "/second"}
139
+ JSON
140
+ end
141
+
142
+ it { expect(resource.relation(:self)).to eq '/first' }
143
+ end
144
+
145
+ context 'relation fields without URLs' do
146
+ let(:body) do
147
+ <<-JSON
148
+ {"a_url": null, "c_url": "", "d_url": 42, "e_url": 1.5,
149
+ "f_url": true, "g_url": {"href": "/g"}, "h_url": ["/h"]}
150
+ JSON
151
+ end
152
+
153
+ it { expect(resource._restify_relations).to be_empty }
154
+ end
155
+
156
+ context 'fields similar to relations' do
157
+ let(:body) do
158
+ <<-JSON
159
+ {"_url": "/a", "url_b": "/b"}
160
+ JSON
161
+ end
162
+
163
+ it { expect(resource._restify_relations).to be_empty }
164
+ end
165
+
166
+ context 'relation fields with non-ASCII characters' do
167
+ let(:body) do
168
+ <<-JSON
169
+ {"\u00FCber_url": "/a", "\u212A_url": "/kelvin", "\u212Aurl": "/b"}
170
+ JSON
171
+ end
172
+
173
+ it { expect(resource._restify_relations).to be_empty }
174
+ end
175
+
73
176
  context 'single array' do
74
177
  let(:body) do
75
178
  <<-JSON
@@ -41,6 +41,42 @@ describe Restify::Processors::Msgpack do
41
41
 
42
42
  before { allow(response).to receive(:body).and_return(body) }
43
43
 
44
+ describe 'empty body' do
45
+ let(:body) { '' }
46
+
47
+ it { is_expected.to be_a Restify::Resource }
48
+ it { expect(resource.data).to be_nil }
49
+ end
50
+
51
+ describe 'invalid body' do
52
+ let(:body) { "\xC1".b }
53
+
54
+ before do
55
+ allow(response).to receive_messages(
56
+ uri: Addressable::URI.parse('http://test.host/'),
57
+ links: Restify::Link.parse('<http://test.host/other>; rel="other"'),
58
+ )
59
+ end
60
+
61
+ it { is_expected.to be_a Restify::Resource }
62
+ it { is_expected.to have_relation :other }
63
+ it { expect(resource.response).to be response }
64
+
65
+ it 'raises on accessing data' do
66
+ expect { resource.data }.to raise_error(Restify::ParseError) do |error|
67
+ expect(error.response).to be response
68
+ expect(error.cause).to be_a MessagePack::MalformedFormatError
69
+ end
70
+ end
71
+
72
+ it 'raises on accessing delegated data' do
73
+ expect { resource['json'] }.to raise_error Restify::ParseError
74
+ end
75
+
76
+ it { is_expected.not_to respond_to :each }
77
+ it { expect(resource.inspect).to include '@error=' }
78
+ end
79
+
44
80
  describe 'parsing' do
45
81
  context 'single object' do
46
82
  let(:body) do