rest-client 1.6.7 → 1.6.8.rc1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rest-client might be problematic. Click here for more details.

@@ -9,14 +9,14 @@ module RestClient
9
9
  def generate(params)
10
10
  if params.is_a?(String)
11
11
  Base.new(params)
12
- elsif params.respond_to?(:read)
13
- Streamed.new(params)
14
- elsif params
12
+ elsif params.is_a?(Hash)
15
13
  if params.delete(:multipart) == true || has_file?(params)
16
14
  Multipart.new(params)
17
15
  else
18
16
  UrlEncoded.new(params)
19
17
  end
18
+ elsif params.respond_to?(:read)
19
+ Streamed.new(params)
20
20
  else
21
21
  nil
22
22
  end
@@ -44,7 +44,7 @@ module RestClient
44
44
  has_file_array?(v)
45
45
  else
46
46
  v.respond_to?(:path) && v.respond_to?(:read)
47
- end
47
+ end
48
48
  end
49
49
  end
50
50
 
@@ -147,12 +147,17 @@ module RestClient
147
147
 
148
148
  # for UrlEncoded escape the keys
149
149
  def handle_key key
150
- URI.escape(key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
150
+ parser.escape(key.to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
151
151
  end
152
152
 
153
153
  def headers
154
154
  super.merge({'Content-Type' => 'application/x-www-form-urlencoded'})
155
155
  end
156
+
157
+ private
158
+ def parser
159
+ URI.const_defined?(:Parser) ? URI::Parser.new : URI
160
+ end
156
161
  end
157
162
 
158
163
  class Multipart < Base
@@ -0,0 +1,29 @@
1
+ module RestClient
2
+ module Platform
3
+ # Return true if we are running on a darwin-based Ruby platform. This will
4
+ # be false for jruby even on OS X.
5
+ #
6
+ # @return [Boolean]
7
+ def self.mac?
8
+ RUBY_PLATFORM.include?('darwin')
9
+ end
10
+
11
+ # Return true if we are running on Windows.
12
+ #
13
+ # @return [Boolean]
14
+ #
15
+ def self.windows?
16
+ # Ruby only sets File::ALT_SEPARATOR on Windows, and the Ruby standard
17
+ # library uses that to test what platform it's on.
18
+ !!File::ALT_SEPARATOR
19
+ end
20
+
21
+ # Return true if we are running on jruby.
22
+ #
23
+ # @return [Boolean]
24
+ #
25
+ def self.jruby?
26
+ RUBY_PLATFORM == 'java'
27
+ end
28
+ end
29
+ end
@@ -22,12 +22,14 @@ module RestClient
22
22
  # * :verify_ssl enable ssl verification, possible values are constants from OpenSSL::SSL
23
23
  # * :timeout and :open_timeout passing in -1 will disable the timeout by setting the corresponding net timeout values to nil
24
24
  # * :ssl_client_cert, :ssl_client_key, :ssl_ca_file
25
+ # * :ssl_verify_callback, :ssl_verify_callback_warnings
25
26
  class Request
26
27
 
27
28
  attr_reader :method, :url, :headers, :cookies,
28
29
  :payload, :user, :password, :timeout, :max_redirects,
29
30
  :open_timeout, :raw_response, :verify_ssl, :ssl_client_cert,
30
- :ssl_client_key, :ssl_ca_file, :processed_headers, :args
31
+ :ssl_client_key, :ssl_ca_file, :processed_headers, :args,
32
+ :ssl_verify_callback, :ssl_verify_callback_warnings
31
33
 
32
34
  def self.execute(args, & block)
33
35
  new(args).execute(& block)
@@ -53,6 +55,8 @@ module RestClient
53
55
  @ssl_client_cert = args[:ssl_client_cert] || nil
54
56
  @ssl_client_key = args[:ssl_client_key] || nil
55
57
  @ssl_ca_file = args[:ssl_ca_file] || nil
58
+ @ssl_verify_callback = args[:ssl_verify_callback] || nil
59
+ @ssl_verify_callback_warnings = args.fetch(:ssl_verify_callback, true)
56
60
  @tf = nil # If you are a raw request, this is your tempfile
57
61
  @max_redirects = args[:max_redirects] || 10
58
62
  @processed_headers = make_headers headers
@@ -129,29 +133,40 @@ module RestClient
129
133
  if p[k].is_a? Hash
130
134
  process_payload(p[k], key)
131
135
  else
132
- value = URI.escape(p[k].to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
136
+ value = parser.escape(p[k].to_s, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]"))
133
137
  "#{key}=#{value}"
134
138
  end
135
139
  end.join("&")
136
140
  end
137
141
  end
138
142
 
143
+ def print_verify_callback_warnings
144
+ warned = false
145
+ if RestClient::Platform.mac?
146
+ warn('warning: ssl_verify_callback return code is ignored on OS X')
147
+ warned = true
148
+ end
149
+ if RestClient::Platform.jruby?
150
+ warn('warning: SSL verify_callback may not work correctly in jruby')
151
+ warn('see https://github.com/jruby/jruby/issues/597')
152
+ warned = true
153
+ end
154
+ warned
155
+ end
156
+
139
157
  def transmit uri, req, payload, & block
140
158
  setup_credentials req
141
159
 
142
160
  net = net_http_class.new(uri.host, uri.port)
143
161
  net.use_ssl = uri.is_a?(URI::HTTPS)
144
- if (@verify_ssl == false) || (@verify_ssl == OpenSSL::SSL::VERIFY_NONE)
145
- net.verify_mode = OpenSSL::SSL::VERIFY_NONE
146
- elsif @verify_ssl.is_a? Integer
147
- net.verify_mode = @verify_ssl
148
- net.verify_callback = lambda do |preverify_ok, ssl_context|
149
- if (!preverify_ok) || ssl_context.error != 0
150
- err_msg = "SSL Verification failed -- Preverify: #{preverify_ok}, Error: #{ssl_context.error_string} (#{ssl_context.error})"
151
- raise SSLCertificateNotVerified.new(err_msg)
152
- end
153
- true
162
+ if @verify_ssl
163
+ if @verify_ssl.is_a? Integer
164
+ net.verify_mode = @verify_ssl
165
+ else
166
+ net.verify_mode = OpenSSL::SSL::VERIFY_PEER
154
167
  end
168
+ else
169
+ net.verify_mode = OpenSSL::SSL::VERIFY_NONE
155
170
  end
156
171
  net.cert = @ssl_client_cert if @ssl_client_cert
157
172
  net.key = @ssl_client_key if @ssl_client_key
@@ -161,7 +176,26 @@ module RestClient
161
176
 
162
177
  # disable the timeout if the timeout value is -1
163
178
  net.read_timeout = nil if @timeout == -1
164
- net.out_timeout = nil if @open_timeout == -1
179
+ net.open_timeout = nil if @open_timeout == -1
180
+
181
+ # verify_callback isn't well supported on all platforms, but do allow
182
+ # users to set one if they want.
183
+ if ssl_verify_callback
184
+ net.verify_callback = ssl_verify_callback
185
+
186
+ # Hilariously, jruby only calls the callback when cert_store is set to
187
+ # something, so make sure to set one.
188
+ # https://github.com/jruby/jruby/issues/597
189
+ if RestClient::Platform.jruby?
190
+ net.cert_store ||= OpenSSL::X509::Store.new
191
+ end
192
+
193
+ if ssl_verify_callback_warnings != false
194
+ if print_verify_callback_warnings
195
+ warn('pass :ssl_verify_callback_warnings => false to silence this')
196
+ end
197
+ end
198
+ end
165
199
 
166
200
  RestClient.before_execution_procs.each do |before_proc|
167
201
  before_proc.call(req, args)
@@ -182,6 +216,11 @@ module RestClient
182
216
  raise RestClient::ServerBrokeConnection
183
217
  rescue Timeout::Error
184
218
  raise RestClient::RequestTimeout
219
+ rescue OpenSSL::SSL::SSLError => error
220
+ # UGH. Not sure if this is needed at all. SSLCertificateNotVerified is not being used internally.
221
+ # I think it would be better to leave SSLError processing to the client (they'd have to do that anyway...)
222
+ raise SSLCertificateNotVerified.new(error.message) if error.message.include?("certificate verify failed")
223
+ raise error
185
224
  end
186
225
 
187
226
  def setup_credentials(req)
@@ -295,6 +334,11 @@ module RestClient
295
334
  {:accept => '*/*; q=0.5, application/xml', :accept_encoding => 'gzip, deflate'}
296
335
  end
297
336
 
337
+ private
338
+ def parser
339
+ URI.const_defined?(:Parser) ? URI::Parser.new : URI
340
+ end
341
+
298
342
  end
299
343
  end
300
344
 
@@ -6,7 +6,9 @@ module RestClient
6
6
 
7
7
  include AbstractResponse
8
8
 
9
- attr_accessor :args, :body, :net_http_res
9
+ attr_accessor :args, :net_http_res
10
+
11
+ attr_writer :body
10
12
 
11
13
  def body
12
14
  self
@@ -0,0 +1,7 @@
1
+ module RestClient
2
+ VERSION = '1.6.8.rc1' unless defined?(self::VERSION)
3
+
4
+ def self.version
5
+ VERSION
6
+ end
7
+ end
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.expand_path("../lib/restclient/version", __FILE__)
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'rest-client'
7
+ s.version = RestClient::VERSION
8
+ s.authors = ['REST Client Team']
9
+ s.description = 'A simple HTTP and REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete.'
10
+ s.license = 'MIT'
11
+ s.email = 'rest.client@librelist.com'
12
+ s.executables = ['restclient']
13
+ s.extra_rdoc_files = ["README.rdoc", "history.md"]
14
+ s.files = `git ls-files`.split("\n")
15
+ s.test_files = `git ls-files -- spec/*`.split("\n")
16
+ s.homepage = 'https://github.com/rest-client/rest-client'
17
+ s.summary = 'Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions.'
18
+
19
+ s.add_dependency(%q<mime-types>, ["~> 1.16"])
20
+ s.add_dependency(%q<rdoc>, [">= 2.4.2"])
21
+ s.add_development_dependency(%q<rake>, ["~> 10.0"])
22
+ s.add_development_dependency(%q<webmock>, ["~> 1.4"])
23
+ s.add_development_dependency(%q<rspec>, ["~> 2.4"])
24
+ s.add_development_dependency(%q<pry>)
25
+ end
26
+
@@ -16,55 +16,55 @@ describe RestClient::AbstractResponse do
16
16
  end
17
17
 
18
18
  before do
19
- @net_http_res = mock('net http response')
19
+ @net_http_res = double('net http response')
20
20
  @response = MyAbstractResponse.new(@net_http_res, {})
21
21
  end
22
22
 
23
23
  it "fetches the numeric response code" do
24
24
  @net_http_res.should_receive(:code).and_return('200')
25
- @response.code.should == 200
25
+ @response.code.should eq 200
26
26
  end
27
27
 
28
28
  it "has a nice description" do
29
29
  @net_http_res.should_receive(:to_hash).and_return({'Content-Type' => ['application/pdf']})
30
30
  @net_http_res.should_receive(:code).and_return('200')
31
- @response.description == '200 OK | application/pdf bytes\n'
31
+ @response.description.should eq "200 OK | application/pdf bytes\n"
32
32
  end
33
33
 
34
34
  it "beautifies the headers by turning the keys to symbols" do
35
35
  h = RestClient::AbstractResponse.beautify_headers('content-type' => [ 'x' ])
36
- h.keys.first.should == :content_type
36
+ h.keys.first.should eq :content_type
37
37
  end
38
38
 
39
39
  it "beautifies the headers by turning the values to strings instead of one-element arrays" do
40
40
  h = RestClient::AbstractResponse.beautify_headers('x' => [ 'text/html' ] )
41
- h.values.first.should == 'text/html'
41
+ h.values.first.should eq 'text/html'
42
42
  end
43
43
 
44
44
  it "fetches the headers" do
45
45
  @net_http_res.should_receive(:to_hash).and_return('content-type' => [ 'text/html' ])
46
- @response.headers.should == { :content_type => 'text/html' }
46
+ @response.headers.should eq({ :content_type => 'text/html' })
47
47
  end
48
48
 
49
49
  it "extracts cookies from response headers" do
50
50
  @net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=1; path=/'])
51
- @response.cookies.should == { 'session_id' => '1' }
51
+ @response.cookies.should eq({ 'session_id' => '1' })
52
52
  end
53
53
 
54
54
  it "extract strange cookies" do
55
55
  @net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=ZJ/HQVH6YE+rVkTpn0zvTQ==; path=/'])
56
- @response.cookies.should == { 'session_id' => 'ZJ%2FHQVH6YE+rVkTpn0zvTQ%3D%3D' }
56
+ @response.cookies.should eq({ 'session_id' => 'ZJ%2FHQVH6YE+rVkTpn0zvTQ%3D%3D' })
57
57
  end
58
58
 
59
59
  it "doesn't escape cookies" do
60
60
  @net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=BAh7BzoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOgpsb2dpbiIKYWRtaW4%3D%0A--08114ba654f17c04d20dcc5228ec672508f738ca; path=/'])
61
- @response.cookies.should == { 'session_id' => 'BAh7BzoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOgpsb2dpbiIKYWRtaW4%3D%0A--08114ba654f17c04d20dcc5228ec672508f738ca' }
61
+ @response.cookies.should eq({ 'session_id' => 'BAh7BzoNYXBwX25hbWUiEGFwcGxpY2F0aW9uOgpsb2dpbiIKYWRtaW4%3D%0A--08114ba654f17c04d20dcc5228ec672508f738ca' })
62
62
  end
63
63
 
64
64
  it "can access the net http result directly" do
65
- @response.net_http_res.should == @net_http_res
65
+ @response.net_http_res.should eq @net_http_res
66
66
  end
67
-
67
+
68
68
  describe "#return!" do
69
69
  it "should return the response itself on 200-codes" do
70
70
  @net_http_res.should_receive(:code).and_return('200')
@@ -75,7 +75,7 @@ describe RestClient::AbstractResponse do
75
75
  @net_http_res.should_receive(:code).and_return('1000')
76
76
  lambda { @response.return! }.should raise_error RestClient::RequestFailed
77
77
  end
78
-
78
+
79
79
  it "should raise an error on a redirection after non-GET/HEAD requests" do
80
80
  @net_http_res.should_receive(:code).and_return('301')
81
81
  @response.args.merge(:method => :put)
data/spec/base.rb CHANGED
@@ -1,11 +1,8 @@
1
1
  def is_ruby_19?
2
- RUBY_VERSION == '1.9.1' or RUBY_VERSION == '1.9.2'
2
+ RUBY_VERSION > '1.9'
3
3
  end
4
4
 
5
- Encoding.default_internal = Encoding.default_external = "ASCII-8BIT" if is_ruby_19?
6
-
7
5
  require 'rubygems'
8
- require 'spec'
9
6
 
10
7
  begin
11
8
  require "ruby-debug"
@@ -1,23 +1,23 @@
1
1
  require File.join( File.dirname(File.expand_path(__FILE__)), 'base')
2
2
 
3
3
  require 'webmock/rspec'
4
- include WebMock
4
+ include WebMock::API
5
5
 
6
6
  describe RestClient::Exception do
7
7
  it "returns a 'message' equal to the class name if the message is not set, because 'message' should not be nil" do
8
8
  e = RestClient::Exception.new
9
- e.message.should == "RestClient::Exception"
9
+ e.message.should eq "RestClient::Exception"
10
10
  end
11
-
11
+
12
12
  it "returns the 'message' that was set" do
13
13
  e = RestClient::Exception.new
14
14
  message = "An explicitly set message"
15
15
  e.message = message
16
- e.message.should == message
16
+ e.message.should eq message
17
17
  end
18
-
18
+
19
19
  it "sets the exception message to ErrorMessage" do
20
- RestClient::ResourceNotFound.new.message.should == 'Resource Not Found'
20
+ RestClient::ResourceNotFound.new.message.should eq 'Resource Not Found'
21
21
  end
22
22
 
23
23
  it "contains exceptions in RestClient" do
@@ -29,13 +29,13 @@ end
29
29
  describe RestClient::ServerBrokeConnection do
30
30
  it "should have a default message of 'Server broke connection'" do
31
31
  e = RestClient::ServerBrokeConnection.new
32
- e.message.should == 'Server broke connection'
32
+ e.message.should eq 'Server broke connection'
33
33
  end
34
34
  end
35
35
 
36
36
  describe RestClient::RequestFailed do
37
37
  before do
38
- @response = mock('HTTP Response', :code => '502')
38
+ @response = double('HTTP Response', :code => '502')
39
39
  end
40
40
 
41
41
  it "stores the http response on the exception" do
@@ -43,17 +43,17 @@ describe RestClient::RequestFailed do
43
43
  begin
44
44
  raise RestClient::RequestFailed, response
45
45
  rescue RestClient::RequestFailed => e
46
- e.response.should == response
46
+ e.response.should eq response
47
47
  end
48
48
  end
49
49
 
50
50
  it "http_code convenience method for fetching the code as an integer" do
51
- RestClient::RequestFailed.new(@response).http_code.should == 502
51
+ RestClient::RequestFailed.new(@response).http_code.should eq 502
52
52
  end
53
53
 
54
54
  it "http_body convenience method for fetching the body (decoding when necessary)" do
55
- RestClient::RequestFailed.new(@response).http_code.should == 502
56
- RestClient::RequestFailed.new(@response).message.should == 'HTTP status code 502'
55
+ RestClient::RequestFailed.new(@response).http_code.should eq 502
56
+ RestClient::RequestFailed.new(@response).message.should eq 'HTTP status code 502'
57
57
  end
58
58
 
59
59
  it "shows the status code in the message" do
@@ -67,22 +67,22 @@ describe RestClient::ResourceNotFound do
67
67
  begin
68
68
  raise RestClient::ResourceNotFound, response
69
69
  rescue RestClient::ResourceNotFound => e
70
- e.response.should == response
70
+ e.response.should eq response
71
71
  end
72
72
  end
73
73
  end
74
74
 
75
75
  describe "backwards compatibility" do
76
76
  it "alias RestClient::Request::Redirect to RestClient::Redirect" do
77
- RestClient::Request::Redirect.should == RestClient::Redirect
77
+ RestClient::Request::Redirect.should eq RestClient::Redirect
78
78
  end
79
79
 
80
80
  it "alias RestClient::Request::Unauthorized to RestClient::Unauthorized" do
81
- RestClient::Request::Unauthorized.should == RestClient::Unauthorized
81
+ RestClient::Request::Unauthorized.should eq RestClient::Unauthorized
82
82
  end
83
83
 
84
84
  it "alias RestClient::Request::RequestFailed to RestClient::RequestFailed" do
85
- RestClient::Request::RequestFailed.should == RestClient::RequestFailed
85
+ RestClient::Request::RequestFailed.should eq RestClient::RequestFailed
86
86
  end
87
87
 
88
88
  it "make the exception's response act like an Net::HTTPResponse" do
@@ -92,7 +92,7 @@ describe "backwards compatibility" do
92
92
  RestClient.get "www.example.com"
93
93
  raise
94
94
  rescue RestClient::ResourceNotFound => e
95
- e.response.body.should == body
95
+ e.response.body.should eq body
96
96
  end
97
97
  end
98
98
  end
@@ -0,0 +1,19 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
3
+ EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
4
+ KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
5
+ MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
6
+ MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
7
+ Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
8
+ Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
9
+ OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
10
+ MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
11
+ NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
12
+ h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
13
+ Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
14
+ JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
15
+ V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
16
+ myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
17
+ mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
18
+ vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
19
+ -----END CERTIFICATE-----