rest-man 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (133) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/{multi-matrix-test.yml → ci.yml} +10 -1
  3. data/.github/workflows/single-matrix-test.yml +1 -0
  4. data/.gitignore +2 -0
  5. data/.rubocop-disables.yml +4 -29
  6. data/AUTHORS +5 -1
  7. data/CHANGELOG.md +14 -0
  8. data/Gemfile +3 -0
  9. data/README.md +30 -37
  10. data/Rakefile +1 -59
  11. data/_doc/lib/restman/abstract_response/_follow_redirection.rdoc +7 -0
  12. data/_doc/lib/restman/abstract_response/beautify_headers.rdoc +24 -0
  13. data/_doc/lib/restman/abstract_response/cookie_jar.rdoc +4 -0
  14. data/_doc/lib/restman/abstract_response/cookies.rdoc +12 -0
  15. data/_doc/lib/restman/abstract_response/follow_get_redirection.rdoc +2 -0
  16. data/_doc/lib/restman/abstract_response/follow_redirection.rdoc +2 -0
  17. data/_doc/lib/restman/abstract_response/headers.rdoc +2 -0
  18. data/_doc/lib/restman/abstract_response/response_set_vars.rdoc +5 -0
  19. data/_doc/lib/restman/abstract_response/return.rdoc +9 -0
  20. data/_doc/lib/restman/add_before_execution_proc.rdoc +2 -0
  21. data/_doc/lib/restman/create_log.rdoc +2 -0
  22. data/_doc/lib/restman/exception.rdoc +6 -0
  23. data/_doc/lib/restman/exceptions/timeout.rdoc +4 -0
  24. data/_doc/lib/restman/exceptions.rdoc +4 -0
  25. data/_doc/lib/restman/log=.rdoc +3 -0
  26. data/_doc/lib/restman/params_array/new.rdoc +20 -0
  27. data/_doc/lib/restman/params_array/process_pair.rdoc +4 -0
  28. data/_doc/lib/restman/params_array.rdoc +11 -0
  29. data/_doc/lib/restman/platform/jruby?.rdoc +4 -0
  30. data/_doc/lib/restman/platform/mac_mri?.rdoc +5 -0
  31. data/_doc/lib/restman/proxy.rdoc +2 -0
  32. data/_doc/lib/restman/proxy_set?.rdoc +5 -0
  33. data/_doc/lib/restman/raw_response/new.rdoc +6 -0
  34. data/_doc/lib/restman/raw_response.rdoc +10 -0
  35. data/_doc/lib/restman/request/cookie_jar.rdoc +3 -0
  36. data/_doc/lib/restman/request/cookies.rdoc +11 -0
  37. data/_doc/lib/restman/request/default_headers.rdoc +5 -0
  38. data/_doc/lib/restman/request/default_ssl_cert_store.rdoc +8 -0
  39. data/_doc/lib/restman/request/init/cookie_jar.rdoc +55 -0
  40. data/_doc/lib/restman/request/init/http_method.rdoc +15 -0
  41. data/_doc/lib/restman/request/make_cookie_header.rdoc +8 -0
  42. data/_doc/lib/restman/request/make_headers.rdoc +25 -0
  43. data/_doc/lib/restman/request/maybe_convert_extension.rdoc +18 -0
  44. data/_doc/lib/restman/request/process_result.rdoc +4 -0
  45. data/_doc/lib/restman/request/proxy_uri.rdoc +7 -0
  46. data/_doc/lib/restman/request/stringify_headers.rdoc +9 -0
  47. data/_doc/lib/restman/request/use_ssl.rdoc +4 -0
  48. data/_doc/lib/restman/request.rdoc +46 -0
  49. data/_doc/lib/restman/reset_before_execution_procs.rdoc +1 -0
  50. data/_doc/lib/restman/resource/[].rdoc +25 -0
  51. data/_doc/lib/restman/resource.rdoc +33 -0
  52. data/_doc/lib/restman/response/body.rdoc +7 -0
  53. data/_doc/lib/restman/response/create.rdoc +10 -0
  54. data/_doc/lib/restman/response/fix_encoding.rdoc +2 -0
  55. data/_doc/lib/restman/statuses.rdoc +11 -0
  56. data/_doc/lib/restman/utils/cgi_parse_header.rdoc +6 -0
  57. data/_doc/lib/restman/utils/encode_query_string.rdoc +90 -0
  58. data/_doc/lib/restman/utils/escape.rdoc +11 -0
  59. data/_doc/lib/restman/utils/flatten_params.rdoc +16 -0
  60. data/_doc/lib/restman/utils/get_encoding_from_headers.rdoc +24 -0
  61. data/_doc/lib/restman.rdoc +43 -0
  62. data/bin/console +15 -0
  63. data/lib/restman/abstract_response.rb +13 -60
  64. data/lib/restman/exception.rb +43 -0
  65. data/lib/restman/exceptions/exception_with_response.rb +7 -0
  66. data/lib/restman/exceptions/exceptions_map.rb +26 -0
  67. data/lib/restman/exceptions/request_failed.rb +15 -0
  68. data/lib/restman/exceptions/server_broke_connection.rb +13 -0
  69. data/lib/restman/exceptions/timeout.rb +37 -0
  70. data/lib/restman/params_array/process_pair.rb +39 -0
  71. data/lib/restman/params_array.rb +3 -48
  72. data/lib/restman/payload/base.rb +57 -0
  73. data/lib/restman/payload/multipart/write_content_disposition.rb +88 -0
  74. data/lib/restman/payload/multipart.rb +56 -0
  75. data/lib/restman/payload/streamed.rb +22 -0
  76. data/lib/restman/payload/url_encoded.rb +14 -0
  77. data/lib/restman/payload.rb +14 -196
  78. data/lib/restman/platform.rb +2 -18
  79. data/lib/restman/raw_response.rb +2 -14
  80. data/lib/restman/request/default_ssl_cert_store.rb +13 -0
  81. data/lib/restman/request/fetch_body_to_tempfile.rb +58 -0
  82. data/lib/restman/request/init/cookie_jar.rb +65 -0
  83. data/lib/restman/request/init/ssl_opts.rb +70 -0
  84. data/lib/restman/request/init/url/add_query_from_headers.rb +51 -0
  85. data/lib/restman/request/init/url/normalize_url.rb +19 -0
  86. data/lib/restman/request/init/url.rb +40 -0
  87. data/lib/restman/request/init.rb +106 -0
  88. data/lib/restman/request/log_request.rb +46 -0
  89. data/lib/restman/request/make_cookie_header.rb +16 -0
  90. data/lib/restman/request/make_headers.rb +39 -0
  91. data/lib/restman/request/maybe_convert_extension.rb +28 -0
  92. data/lib/restman/request/net_http_object.rb +25 -0
  93. data/lib/restman/request/process_result.rb +36 -0
  94. data/lib/restman/request/proxy_uri.rb +31 -0
  95. data/lib/restman/request/stringify_headers.rb +36 -0
  96. data/lib/restman/request/transmit.rb +152 -0
  97. data/lib/restman/request.rb +60 -745
  98. data/lib/restman/resource.rb +2 -60
  99. data/lib/restman/response.rb +3 -21
  100. data/lib/restman/statuses.rb +75 -0
  101. data/lib/restman/statuses_compatibility.rb +18 -0
  102. data/lib/restman/utils.rb +10 -206
  103. data/lib/restman/version.rb +1 -1
  104. data/lib/restman.rb +24 -62
  105. data/matrixeval.yml +19 -1
  106. data/rest-man.gemspec +4 -10
  107. data/spec/integration/capath_digicert/ce5e74ef.0 +1 -1
  108. data/spec/integration/request_spec.rb +13 -1
  109. data/spec/spec_helper.rb +11 -0
  110. data/spec/unit/abstract_response_spec.rb +14 -0
  111. data/spec/unit/exception_spec.rb +64 -0
  112. data/spec/unit/exceptions/backwards_campatibility_spec.rb +29 -0
  113. data/spec/unit/exceptions/exceptions_map_spec.rb +89 -0
  114. data/spec/unit/exceptions/request_failed_spec.rb +51 -0
  115. data/spec/unit/exceptions/server_broke_connection_spec.rb +8 -0
  116. data/spec/unit/exceptions/timeout_spec.rb +59 -0
  117. data/spec/unit/params_array/process_pair_spec.rb +59 -0
  118. data/spec/unit/params_array_spec.rb +15 -10
  119. data/spec/unit/payload/multipart_spec.rb +116 -0
  120. data/spec/unit/payload/streamed_spec.rb +48 -0
  121. data/spec/unit/payload/url_encoded_spec.rb +65 -0
  122. data/spec/unit/payload_spec.rb +0 -208
  123. data/spec/unit/request/init/url/add_query_from_headers_spec.rb +40 -0
  124. data/spec/unit/request/init/url/normalize_url_spec.rb +25 -0
  125. data/spec/unit/request/init_spec.rb +83 -0
  126. data/spec/unit/request_spec.rb +143 -151
  127. data/spec/unit/utils_spec.rb +96 -104
  128. metadata +132 -16
  129. data/lib/restman/exceptions.rb +0 -238
  130. data/lib/restman/windows/root_certs.rb +0 -105
  131. data/lib/restman/windows.rb +0 -8
  132. data/spec/unit/exceptions_spec.rb +0 -108
  133. data/spec/unit/windows/root_certs_spec.rb +0 -22
@@ -20,6 +20,10 @@ describe RestMan::Request, :include_helpers do
20
20
  allow(@net).to receive(:verify_callback=)
21
21
  allow(@net).to receive(:ciphers=)
22
22
  allow(@net).to receive(:cert_store=)
23
+ allow(@net).to receive(:max_retries=)
24
+ allow(@net).to receive(:read_timeout=)
25
+ allow(@net).to receive(:write_timeout=)
26
+ allow(@net).to receive(:open_timeout=)
23
27
  RestMan.log = nil
24
28
  end
25
29
 
@@ -46,48 +50,17 @@ describe RestMan::Request, :include_helpers do
46
50
  end
47
51
  end
48
52
 
49
- describe '.normalize_url' do
50
- it "adds http:// to the front of resources specified in the syntax example.com/resource" do
51
- expect(@request.normalize_url('example.com/resource')).to eq 'http://example.com/resource'
52
- end
53
-
54
- it 'adds http:// to resources containing a colon' do
55
- expect(@request.normalize_url('example.com:1234')).to eq 'http://example.com:1234'
56
- end
57
-
58
- it 'does not add http:// to the front of https resources' do
59
- expect(@request.normalize_url('https://example.com/resource')).to eq 'https://example.com/resource'
60
- end
61
-
62
- it 'does not add http:// to the front of capital HTTP resources' do
63
- expect(@request.normalize_url('HTTP://example.com/resource')).to eq 'HTTP://example.com/resource'
64
- end
65
-
66
- it 'does not add http:// to the front of capital HTTPS resources' do
67
- expect(@request.normalize_url('HTTPS://example.com/resource')).to eq 'HTTPS://example.com/resource'
68
- end
69
-
70
- it 'raises with invalid URI' do
71
- expect {
72
- RestMan::Request.new(method: :get, url: 'http://a@b:c')
73
- }.to raise_error(URI::InvalidURIError)
74
- expect {
75
- RestMan::Request.new(method: :get, url: 'http://::')
76
- }.to raise_error(URI::InvalidURIError)
77
- end
78
- end
79
-
80
53
  describe "user - password" do
81
54
  it "extracts the username and password when parsing http://user:password@example.com/" do
82
- @request.send(:parse_url_with_auth!, 'http://joe:pass1@example.com/resource')
83
- expect(@request.user).to eq 'joe'
84
- expect(@request.password).to eq 'pass1'
55
+ request = RestMan::Request.new(method: :get, url: 'http://joe:pass1@example.com/resource')
56
+ expect(request.user).to eq 'joe'
57
+ expect(request.password).to eq 'pass1'
85
58
  end
86
59
 
87
60
  it "extracts with escaping the username and password when parsing http://user:password@example.com/" do
88
- @request.send(:parse_url_with_auth!, 'http://joe%20:pass1@example.com/resource')
89
- expect(@request.user).to eq 'joe '
90
- expect(@request.password).to eq 'pass1'
61
+ request = RestMan::Request.new(method: :get, url: 'http://joe%20:pass1@example.com/resource')
62
+ expect(request.user).to eq 'joe '
63
+ expect(request.password).to eq 'pass1'
91
64
  end
92
65
 
93
66
  it "doesn't overwrite user and password (which may have already been set by the Resource constructor) if there is no user/password in the url" do
@@ -236,31 +209,14 @@ describe RestMan::Request, :include_helpers do
236
209
  end
237
210
  end
238
211
 
239
- it 'warns when overriding existing headers via payload' do
240
- expect(fake_stderr {
241
- RestMan::Request.new(method: :post, url: 'example.com',
242
- payload: {'foo' => 1}, headers: {content_type: :json})
243
- }).to match(/warning: Overriding "Content-Type" header/i)
244
- expect(fake_stderr {
245
- RestMan::Request.new(method: :post, url: 'example.com',
246
- payload: {'foo' => 1}, headers: {'Content-Type' => 'application/json'})
247
- }).to match(/warning: Overriding "Content-Type" header/i)
248
-
249
- expect(fake_stderr {
250
- RestMan::Request.new(method: :post, url: 'example.com',
251
- payload: '123456', headers: {content_length: '20'})
252
- }).to match(/warning: Overriding "Content-Length" header/i)
253
- expect(fake_stderr {
254
- RestMan::Request.new(method: :post, url: 'example.com',
255
- payload: '123456', headers: {'Content-Length' => '20'})
256
- }).to match(/warning: Overriding "Content-Length" header/i)
257
- end
258
-
259
- it "does not warn when overriding user header with header derived from payload if those header values were identical" do
260
- expect(fake_stderr {
261
- RestMan::Request.new(method: :post, url: 'example.com',
262
- payload: {'foo' => '123456'}, headers: { 'Content-Type' => 'application/x-www-form-urlencoded' })
263
- }).not_to match(/warning: Overriding "Content-Type" header/i)
212
+ it "does not override headers" do
213
+ request = RestMan::Request.new(
214
+ method: :post,
215
+ url: 'example.com',
216
+ payload: {'foo' => '123456'},
217
+ headers: { 'Content-Type' => 'application/x-www-form-urlencoded; charset=UTF-8' }
218
+ )
219
+ expect(request.processed_headers['Content-Type']).to eq('application/x-www-form-urlencoded; charset=UTF-8')
264
220
  end
265
221
 
266
222
  it 'does not warn for a normal looking payload' do
@@ -488,6 +444,12 @@ describe RestMan::Request, :include_helpers do
488
444
  expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestMan::Exceptions::OpenTimeout)
489
445
  end
490
446
 
447
+ it "catches Net::WriteTimeout and raises RestMan's WriteTimeout",
448
+ :if => defined?(Net::WriteTimeout) do
449
+ allow(@http).to receive(:request).and_raise(Net::WriteTimeout)
450
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestMan::Exceptions::WriteTimeout)
451
+ end
452
+
491
453
  it "uses correct error message for ReadTimeout",
492
454
  :if => defined?(Net::ReadTimeout) do
493
455
  allow(@http).to receive(:request).and_raise(Net::ReadTimeout)
@@ -500,6 +462,11 @@ describe RestMan::Request, :include_helpers do
500
462
  expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestMan::Exceptions::OpenTimeout, 'Timed out connecting to server')
501
463
  end
502
464
 
465
+ it "uses correct error message for WriteTimeout",
466
+ :if => defined?(Net::WriteTimeout) do
467
+ allow(@http).to receive(:request).and_raise(Net::WriteTimeout)
468
+ expect { @request.send(:transmit, @uri, 'req', nil) }.to raise_error(RestMan::Exceptions::WriteTimeout, 'Timed out writing data to server')
469
+ end
503
470
 
504
471
  it "class method execute wraps constructor" do
505
472
  req = double("rest request")
@@ -690,17 +657,6 @@ describe RestMan::Request, :include_helpers do
690
657
  end
691
658
 
692
659
  describe "timeout" do
693
- it "does not set timeouts if not specified" do
694
- @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload')
695
- allow(@http).to receive(:request)
696
- allow(@request).to receive(:process_result)
697
-
698
- expect(@net).not_to receive(:read_timeout=)
699
- expect(@net).not_to receive(:open_timeout=)
700
-
701
- @request.send(:transmit, @uri, 'req', nil)
702
- end
703
-
704
660
  it 'sets read_timeout' do
705
661
  @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :read_timeout => 123)
706
662
  allow(@http).to receive(:request)
@@ -721,62 +677,49 @@ describe RestMan::Request, :include_helpers do
721
677
  @request.send(:transmit, @uri, 'req', nil)
722
678
  end
723
679
 
724
- it 'sets both timeouts with :timeout' do
725
- @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123)
680
+ it "sets write_timeout" do
681
+ @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :write_timeout => 123)
726
682
  allow(@http).to receive(:request)
727
683
  allow(@request).to receive(:process_result)
728
684
 
729
- expect(@net).to receive(:open_timeout=).with(123)
730
- expect(@net).to receive(:read_timeout=).with(123)
685
+ expect(@net).to receive(:write_timeout=).with(123)
731
686
 
732
687
  @request.send(:transmit, @uri, 'req', nil)
733
688
  end
734
689
 
735
- it 'supersedes :timeout with open/read_timeout' do
736
- @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123, :open_timeout => 34, :read_timeout => 56)
690
+ it 'sets all timeouts with :timeout' do
691
+ @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123)
737
692
  allow(@http).to receive(:request)
738
693
  allow(@request).to receive(:process_result)
739
694
 
740
- expect(@net).to receive(:open_timeout=).with(34)
741
- expect(@net).to receive(:read_timeout=).with(56)
695
+ expect(@net).to receive(:open_timeout=).with(123)
696
+ expect(@net).to receive(:read_timeout=).with(123)
697
+ expect(@net).to receive(:write_timeout=).with(123)
742
698
 
743
699
  @request.send(:transmit, @uri, 'req', nil)
744
700
  end
745
701
 
746
-
747
- it "disable timeout by setting it to nil" do
748
- @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :read_timeout => nil, :open_timeout => nil)
702
+ it 'supersedes :timeout with open/read/write_timeout' do
703
+ @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123, :open_timeout => 34, :read_timeout => 56, :write_timeout => 78)
749
704
  allow(@http).to receive(:request)
750
705
  allow(@request).to receive(:process_result)
751
706
 
752
- expect(@net).to receive(:read_timeout=).with(nil)
753
- expect(@net).to receive(:open_timeout=).with(nil)
707
+ expect(@net).to receive(:open_timeout=).with(34)
708
+ expect(@net).to receive(:read_timeout=).with(56)
709
+ expect(@net).to receive(:write_timeout=).with(78)
754
710
 
755
711
  @request.send(:transmit, @uri, 'req', nil)
756
712
  end
757
713
 
758
- it 'deprecated: warns when disabling timeout by setting it to -1' do
759
- @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :read_timeout => -1)
760
- allow(@http).to receive(:request)
761
- allow(@request).to receive(:process_result)
762
-
763
- expect(@net).to receive(:read_timeout=).with(nil)
764
-
765
- expect(fake_stderr {
766
- @request.send(:transmit, @uri, 'req', nil)
767
- }).to match(/^Deprecated: .*timeout.* nil instead of -1$/)
768
- end
769
714
 
770
- it "deprecated: disable timeout by setting it to -1" do
771
- @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :read_timeout => -1, :open_timeout => -1)
715
+ it "disable timeout by setting it to nil" do
716
+ @request = RestMan::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :read_timeout => nil, :open_timeout => nil, :write_timeout => nil)
772
717
  allow(@http).to receive(:request)
773
718
  allow(@request).to receive(:process_result)
774
719
 
775
- expect(@request).to receive(:warn)
776
720
  expect(@net).to receive(:read_timeout=).with(nil)
777
-
778
- expect(@request).to receive(:warn)
779
721
  expect(@net).to receive(:open_timeout=).with(nil)
722
+ expect(@net).to receive(:write_timeout=).with(nil)
780
723
 
781
724
  @request.send(:transmit, @uri, 'req', nil)
782
725
  end
@@ -844,6 +787,58 @@ describe RestMan::Request, :include_helpers do
844
787
  @request.send(:transmit, @uri, 'req', 'payload')
845
788
  end
846
789
 
790
+ it "should set the keep_alive_timeout if provided" do
791
+ @request = RestMan::Request.new(
792
+ :method => :put,
793
+ :url => 'https://some/resource',
794
+ :payload => 'payload',
795
+ :keep_alive_timeout => 1
796
+ )
797
+ expect(@net).to receive(:keep_alive_timeout=).with(1)
798
+ allow(@http).to receive(:request)
799
+ allow(@request).to receive(:process_result)
800
+ @request.send(:transmit, @uri, 'req', 'payload')
801
+ end
802
+
803
+ it "should set the close_on_empty_response if provided" do
804
+ @request = RestMan::Request.new(
805
+ :method => :put,
806
+ :url => 'https://some/resource',
807
+ :payload => 'payload',
808
+ :close_on_empty_response => true
809
+ )
810
+ expect(@net).to receive(:close_on_empty_response=).with(true)
811
+ allow(@http).to receive(:request)
812
+ allow(@request).to receive(:process_result)
813
+ @request.send(:transmit, @uri, 'req', 'payload')
814
+ end
815
+
816
+ it "should set the local_host if provided" do
817
+ @request = RestMan::Request.new(
818
+ :method => :put,
819
+ :url => 'https://some/resource',
820
+ :payload => 'payload',
821
+ :local_host => 'localhost'
822
+ )
823
+ expect(@net).to receive(:local_host=).with('localhost')
824
+ allow(@http).to receive(:request)
825
+ allow(@request).to receive(:process_result)
826
+ @request.send(:transmit, @uri, 'req', 'payload')
827
+ end
828
+
829
+ it "should set the local_port if provided" do
830
+ @request = RestMan::Request.new(
831
+ :method => :put,
832
+ :url => 'https://some/resource',
833
+ :payload => 'payload',
834
+ :local_port => 3000
835
+ )
836
+ expect(@net).to receive(:local_port=).with(3000)
837
+ allow(@http).to receive(:request)
838
+ allow(@request).to receive(:process_result)
839
+ @request.send(:transmit, @uri, 'req', 'payload')
840
+ end
841
+
847
842
  it "should default to not having an ssl_client_cert" do
848
843
  expect(@request.ssl_client_cert).to be(nil)
849
844
  end
@@ -873,6 +868,45 @@ describe RestMan::Request, :include_helpers do
873
868
  @request.send(:transmit, @uri, 'req', 'payload')
874
869
  end
875
870
 
871
+ it "should set the ssl_min_version if provided" do
872
+ @request = RestMan::Request.new(
873
+ :method => :put,
874
+ :url => 'https://some/resource',
875
+ :payload => 'payload',
876
+ :ssl_min_version => :TLS1_2
877
+ )
878
+ expect(@net).to receive(:min_version=).with(:TLS1_2)
879
+ allow(@http).to receive(:request)
880
+ allow(@request).to receive(:process_result)
881
+ @request.send(:transmit, @uri, 'req', 'payload')
882
+ end
883
+
884
+ it "should set the ssl_max_version if provided" do
885
+ @request = RestMan::Request.new(
886
+ :method => :put,
887
+ :url => 'https://some/resource',
888
+ :payload => 'payload',
889
+ :ssl_max_version => :TLS1_2
890
+ )
891
+ expect(@net).to receive(:max_version=).with(:TLS1_2)
892
+ allow(@http).to receive(:request)
893
+ allow(@request).to receive(:process_result)
894
+ @request.send(:transmit, @uri, 'req', 'payload')
895
+ end
896
+
897
+ it "should set the ssl_timeout if provided" do
898
+ @request = RestMan::Request.new(
899
+ :method => :put,
900
+ :url => 'https://some/resource',
901
+ :payload => 'payload',
902
+ :ssl_timeout => 1
903
+ )
904
+ expect(@net).to receive(:ssl_timeout=).with(1)
905
+ allow(@http).to receive(:request)
906
+ allow(@request).to receive(:process_result)
907
+ @request.send(:transmit, @uri, 'req', 'payload')
908
+ end
909
+
876
910
  it "should set the ssl_ciphers if provided" do
877
911
  ciphers = 'AESGCM:HIGH:!aNULL:!eNULL:RC4+RSA'
878
912
  @request = RestMan::Request.new(
@@ -1150,56 +1184,14 @@ describe RestMan::Request, :include_helpers do
1150
1184
  end
1151
1185
  end
1152
1186
 
1153
- describe 'constructor' do
1154
- it 'should reject valid URIs with no hostname' do
1155
- expect(URI.parse('http:///').hostname).to be_nil
1156
-
1157
- expect {
1158
- RestMan::Request.new(method: :get, url: 'http:///')
1159
- }.to raise_error(URI::InvalidURIError, /\Abad URI/)
1160
- end
1187
+ it 'raises with invalid URI' do
1188
+ expect {
1189
+ RestMan::Request.new(method: :get, url: 'http://a@b:c')
1190
+ }.to raise_error(URI::InvalidURIError)
1161
1191
 
1162
- it 'should reject invalid URIs' do
1163
- expect {
1164
- RestMan::Request.new(method: :get, url: 'http://::')
1165
- }.to raise_error(URI::InvalidURIError)
1166
- end
1192
+ expect {
1193
+ RestMan::Request.new(method: :get, url: 'http://::')
1194
+ }.to raise_error(URI::InvalidURIError)
1167
1195
  end
1168
1196
 
1169
- describe 'process_url_params' do
1170
- it 'should handle basic URL params' do
1171
- expect(@request.process_url_params('https://example.com/foo', params: {key1: 123, key2: 'abc'})).
1172
- to eq 'https://example.com/foo?key1=123&key2=abc'
1173
-
1174
- expect(@request.process_url_params('https://example.com/foo', params: {'key1' => 123})).
1175
- to eq 'https://example.com/foo?key1=123'
1176
-
1177
- expect(@request.process_url_params('https://example.com/path',
1178
- params: {foo: 'one two', bar: 'three + four == seven'})).
1179
- to eq 'https://example.com/path?foo=one+two&bar=three+%2B+four+%3D%3D+seven'
1180
- end
1181
-
1182
- it 'should combine with & when URL params already exist' do
1183
- expect(@request.process_url_params('https://example.com/path?foo=1', params: {bar: 2})).
1184
- to eq 'https://example.com/path?foo=1&bar=2'
1185
- end
1186
-
1187
- it 'should handle complex nested URL params per Rack / Rails conventions' do
1188
- expect(@request.process_url_params('https://example.com/', params: {
1189
- foo: [1,2,3],
1190
- null: nil,
1191
- falsy: false,
1192
- math: '2+2=4',
1193
- nested: {'key + escaped' => 'value + escaped', other: [], arr: [1,2]},
1194
- })).to eq 'https://example.com/?foo[]=1&foo[]=2&foo[]=3&null&falsy=false&math=2%2B2%3D4' \
1195
- '&nested[key+%2B+escaped]=value+%2B+escaped&nested[other]' \
1196
- '&nested[arr][]=1&nested[arr][]=2'
1197
- end
1198
-
1199
- it 'should handle ParamsArray objects' do
1200
- expect(@request.process_url_params('https://example.com/',
1201
- params: RestMan::ParamsArray.new([[:foo, 1], [:foo, 2]])
1202
- )).to eq 'https://example.com/?foo=1&foo=2'
1203
- end
1204
- end
1205
1197
  end
@@ -1,147 +1,139 @@
1
1
  require_relative '_lib'
2
2
 
3
3
  describe RestMan::Utils do
4
+
4
5
  describe '.get_encoding_from_headers' do
5
- it 'assumes no encoding by default for text' do
6
- headers = {:content_type => 'text/plain'}
7
- expect(RestMan::Utils.get_encoding_from_headers(headers)).
8
- to eq nil
9
- end
10
-
11
- it 'returns nil on failures' do
12
- expect(RestMan::Utils.get_encoding_from_headers(
13
- {:content_type => 'blah'})).to eq nil
14
- expect(RestMan::Utils.get_encoding_from_headers(
15
- {})).to eq nil
16
- expect(RestMan::Utils.get_encoding_from_headers(
17
- {:content_type => 'foo; bar=baz'})).to eq nil
18
- end
19
-
20
- it 'handles various charsets' do
21
- expect(RestMan::Utils.get_encoding_from_headers(
22
- {:content_type => 'text/plain; charset=UTF-8'})).to eq 'UTF-8'
23
- expect(RestMan::Utils.get_encoding_from_headers(
24
- {:content_type => 'application/json; charset=ISO-8859-1'})).
25
- to eq 'ISO-8859-1'
26
- expect(RestMan::Utils.get_encoding_from_headers(
27
- {:content_type => 'text/html; charset=windows-1251'})).
28
- to eq 'windows-1251'
29
-
30
- expect(RestMan::Utils.get_encoding_from_headers(
31
- {:content_type => 'text/html; charset="UTF-16"'})).
32
- to eq 'UTF-16'
6
+
7
+ let(:get_encoding_from_headers) { RestMan::Utils.get_encoding_from_headers(headers) }
8
+
9
+ context 'with valid content_type' do
10
+ let(:headers) {{content_type: 'text/plain'}}
11
+
12
+ it 'assumes no encoding by default' do
13
+ expect(get_encoding_from_headers).to eq(nil)
14
+ end
33
15
  end
34
- end
35
16
 
36
- describe '.cgi_parse_header' do
37
- it 'parses headers', :unless => RUBY_VERSION.start_with?('2.0') do
38
- expect(RestMan::Utils.cgi_parse_header('text/plain')).
39
- to eq ['text/plain', {}]
17
+ context 'with invalid content_type like "blah"' do
18
+ let(:headers) {{content_type: 'blah'}}
40
19
 
41
- expect(RestMan::Utils.cgi_parse_header('text/vnd.just.made.this.up')).
42
- to eq ['text/vnd.just.made.this.up', {}]
20
+ it 'return nil' do
21
+ expect(get_encoding_from_headers).to eq(nil)
22
+ end
23
+ end
43
24
 
44
- expect(RestMan::Utils.cgi_parse_header('text/plain;charset=us-ascii')).
45
- to eq ['text/plain', {'charset' => 'us-ascii'}]
25
+ context 'with invalid content_type like "foo; bar=baz"' do
26
+ let(:headers) {{content_type: 'foo; bar=baz'}}
46
27
 
47
- expect(RestMan::Utils.cgi_parse_header('text/plain ; charset="us-ascii"')).
48
- to eq ['text/plain', {'charset' => 'us-ascii'}]
28
+ it 'return nil' do
29
+ expect(get_encoding_from_headers).to eq(nil)
30
+ end
31
+ end
49
32
 
50
- expect(RestMan::Utils.cgi_parse_header(
51
- 'text/plain ; charset="us-ascii"; another=opt')).
52
- to eq ['text/plain', {'charset' => 'us-ascii', 'another' => 'opt'}]
33
+ context 'with invalid content_type like empty headers' do
34
+ let(:headers) {{}}
53
35
 
54
- expect(RestMan::Utils.cgi_parse_header(
55
- 'foo/bar; filename="silly.txt"')).
56
- to eq ['foo/bar', {'filename' => 'silly.txt'}]
36
+ it 'return nil' do
37
+ expect(get_encoding_from_headers).to eq(nil)
38
+ end
39
+ end
40
+
41
+ context 'with valid content_type with charset UTF-8' do
42
+ let(:headers) {{content_type: 'text/plain; charset=UTF-8'}}
43
+
44
+ it 'return UTF-8' do
45
+ expect(get_encoding_from_headers).to eq('UTF-8')
46
+ end
47
+ end
57
48
 
58
- expect(RestMan::Utils.cgi_parse_header(
59
- 'foo/bar; filename="strange;name"')).
60
- to eq ['foo/bar', {'filename' => 'strange;name'}]
49
+ context 'with valid content_type with charset ISO-8859-1' do
50
+ let(:headers) {{content_type: 'text/plain; charset=ISO-8859-1'}}
61
51
 
62
- expect(RestMan::Utils.cgi_parse_header(
63
- 'foo/bar; filename="strange;name";size=123')).to eq \
64
- ['foo/bar', {'filename' => 'strange;name', 'size' => '123'}]
52
+ it 'return ISO-8859-1' do
53
+ expect(get_encoding_from_headers).to eq('ISO-8859-1')
54
+ end
55
+ end
65
56
 
66
- expect(RestMan::Utils.cgi_parse_header(
67
- 'foo/bar; name="files"; filename="fo\\"o;bar"')).to eq \
68
- ['foo/bar', {'name' => 'files', 'filename' => 'fo"o;bar'}]
57
+ context 'with valid content_type with charset windows-1251' do
58
+ let(:headers) {{content_type: 'text/plain; charset=windows-1251'}}
59
+
60
+ it 'return windows-1251' do
61
+ expect(get_encoding_from_headers).to eq('windows-1251')
62
+ end
69
63
  end
64
+
65
+ context 'with valid content_type with charset UTF-16' do
66
+ let(:headers) {{content_type: 'text/plain; charset=UTF-16'}}
67
+
68
+ it 'return UTF-16' do
69
+ expect(get_encoding_from_headers).to eq('UTF-16')
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+ describe '.cgi_parse_header' do
76
+
77
+ let(:parse) { ->(line, to:) {
78
+ expect(RestMan::Utils.cgi_parse_header(line)).to eq(to)
79
+ }}
80
+
81
+ it { parse.('text/plain', to: ['text/plain', {}]) }
82
+ it { parse.('text/vnd.just.made.this.up', to: ['text/vnd.just.made.this.up', {}]) }
83
+ it { parse.('text/plain;charset=us-ascii', to: ['text/plain', {'charset' => 'us-ascii'}]) }
84
+ it { parse.('text/plain ; charset="us-ascii"', to: ['text/plain', {'charset' => 'us-ascii'}]) }
85
+ it { parse.('text/plain ; charset="us-ascii"; another=opt', to: ['text/plain', {'charset' => 'us-ascii', 'another' => 'opt'}]) }
86
+ it { parse.('foo/bar; filename="silly.txt"', to: ['foo/bar', {'filename' => 'silly.txt'}]) }
87
+ it { parse.('foo/bar; filename="strange;name"', to: ['foo/bar', {'filename' => 'strange;name'}]) }
88
+ it { parse.('foo/bar; filename="strange;name";size=123', to: ['foo/bar', {'filename' => 'strange;name', 'size' => '123'}]) }
89
+ it { parse.('foo/bar; name="files"; filename="fo\\"o;bar"', to: ['foo/bar', {'name' => 'files', 'filename' => 'fo"o;bar'}]) }
90
+
70
91
  end
71
92
 
72
93
  describe '.encode_query_string' do
94
+ let(:encoding) { -> (input, to:) {
95
+ expect(RestMan::Utils.encode_query_string(input)).to eq to
96
+ } }
97
+
73
98
  it 'handles simple hashes' do
74
- {
75
- {foo: 123, bar: 456} => 'foo=123&bar=456',
76
- {'foo' => 123, 'bar' => 456} => 'foo=123&bar=456',
77
- {foo: 'abc', bar: 'one two'} => 'foo=abc&bar=one+two',
78
- {escaped: '1+2=3'} => 'escaped=1%2B2%3D3',
79
- {'escaped + key' => 'foo'} => 'escaped+%2B+key=foo',
80
- }.each_pair do |input, expected|
81
- expect(RestMan::Utils.encode_query_string(input)).to eq expected
82
- end
99
+ encoding.({foo: 123, bar: 456}, to: 'foo=123&bar=456')
100
+ encoding.({'foo' => 123, 'bar' => 456}, to: 'foo=123&bar=456')
101
+ encoding.({foo: 'abc', bar: 'one two'}, to: 'foo=abc&bar=one+two')
102
+ encoding.({escaped: '1+2=3'}, to: 'escaped=1%2B2%3D3')
103
+ encoding.({'escaped + key' => 'foo'}, to: 'escaped+%2B+key=foo')
83
104
  end
84
105
 
85
106
  it 'handles simple arrays' do
86
- {
87
- {foo: [1, 2, 3]} => 'foo[]=1&foo[]=2&foo[]=3',
88
- {foo: %w{a b c}, bar: [1, 2, 3]} => 'foo[]=a&foo[]=b&foo[]=c&bar[]=1&bar[]=2&bar[]=3',
89
- {foo: ['one two', 3]} => 'foo[]=one+two&foo[]=3',
90
- {'a+b' => [1,2,3]} => 'a%2Bb[]=1&a%2Bb[]=2&a%2Bb[]=3',
91
- }.each_pair do |input, expected|
92
- expect(RestMan::Utils.encode_query_string(input)).to eq expected
93
- end
107
+ encoding.({foo: [1, 2, 3]}, to: 'foo[]=1&foo[]=2&foo[]=3')
108
+ encoding.({foo: %w{a b c}, bar: [1, 2, 3]}, to: 'foo[]=a&foo[]=b&foo[]=c&bar[]=1&bar[]=2&bar[]=3')
109
+ encoding.({foo: ['one two', 3]}, to: 'foo[]=one+two&foo[]=3')
110
+ encoding.({'a+b' => [1,2,3]}, to: 'a%2Bb[]=1&a%2Bb[]=2&a%2Bb[]=3')
94
111
  end
95
112
 
96
113
  it 'handles nested hashes' do
97
- {
98
- {outer: {foo: 123, bar: 456}} => 'outer[foo]=123&outer[bar]=456',
99
- {outer: {foo: [1, 2, 3], bar: 'baz'}} => 'outer[foo][]=1&outer[foo][]=2&outer[foo][]=3&outer[bar]=baz',
100
- }.each_pair do |input, expected|
101
- expect(RestMan::Utils.encode_query_string(input)).to eq expected
102
- end
114
+ encoding.({outer: {foo: 123, bar: 456}}, to: 'outer[foo]=123&outer[bar]=456')
115
+ encoding.({outer: {foo: [1, 2, 3], bar: 'baz'}}, to: 'outer[foo][]=1&outer[foo][]=2&outer[foo][]=3&outer[bar]=baz')
103
116
  end
104
117
 
105
118
  it 'handles null and empty values' do
106
- {
107
- {string: '', empty: nil, list: [], hash: {}, falsey: false } =>
108
- 'string=&empty&list&hash&falsey=false',
109
- }.each_pair do |input, expected|
110
- expect(RestMan::Utils.encode_query_string(input)).to eq expected
111
- end
119
+ encoding.({string: '', empty: nil, list: [], hash: {}, falsey: false }, to: 'string=&empty&list&hash&falsey=false')
112
120
  end
113
121
 
114
122
  it 'handles nested nulls' do
115
- {
116
- {foo: {string: '', empty: nil}} => 'foo[string]=&foo[empty]',
117
- }.each_pair do |input, expected|
118
- expect(RestMan::Utils.encode_query_string(input)).to eq expected
119
- end
123
+ encoding.({foo: {string: '', empty: nil}}, to: 'foo[string]=&foo[empty]')
120
124
  end
121
125
 
122
126
  it 'handles deep nesting' do
123
- {
124
- {coords: [{x: 1, y: 0}, {x: 2}, {x: 3}]} => 'coords[][x]=1&coords[][y]=0&coords[][x]=2&coords[][x]=3',
125
- }.each_pair do |input, expected|
126
- expect(RestMan::Utils.encode_query_string(input)).to eq expected
127
- end
127
+ encoding.({coords: [{x: 1, y: 0}, {x: 2}, {x: 3}]}, to: 'coords[][x]=1&coords[][y]=0&coords[][x]=2&coords[][x]=3')
128
128
  end
129
129
 
130
130
  it 'handles multiple fields with the same name using ParamsArray' do
131
- {
132
- RestMan::ParamsArray.new([[:foo, 1], [:foo, 2], [:foo, 3]]) => 'foo=1&foo=2&foo=3',
133
- }.each_pair do |input, expected|
134
- expect(RestMan::Utils.encode_query_string(input)).to eq expected
135
- end
131
+ encoding.(RestMan::ParamsArray.new([[:foo, 1], [:foo, 2], [:foo, 3]]), to: 'foo=1&foo=2&foo=3')
136
132
  end
137
133
 
138
134
  it 'handles nested ParamsArrays' do
139
- {
140
- {foo: RestMan::ParamsArray.new([[:a, 1], [:a, 2]])} => 'foo[a]=1&foo[a]=2',
141
- RestMan::ParamsArray.new([[:foo, {a: 1}], [:foo, {a: 2}]]) => 'foo[a]=1&foo[a]=2',
142
- }.each_pair do |input, expected|
143
- expect(RestMan::Utils.encode_query_string(input)).to eq expected
144
- end
135
+ encoding.({foo: RestMan::ParamsArray.new([[:a, 1], [:a, 2]])}, to: 'foo[a]=1&foo[a]=2')
136
+ encoding.(RestMan::ParamsArray.new([[:foo, {a: 1}], [:foo, {a: 2}]]), to: 'foo[a]=1&foo[a]=2')
145
137
  end
146
138
  end
147
139
  end