isteel-rest-client 0.9.3 → 0.9.3.1

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.
data/README.rdoc CHANGED
@@ -121,18 +121,6 @@ extract and set headers for them as needed:
121
121
  )
122
122
  # ...response body
123
123
 
124
- == SSL Client Certificates
125
-
126
- RestClient::Resource.new(
127
- 'https://example.com',
128
- :ssl_client_cert => OpenSSL::X509::Certificate.new(File.read("cert.pem")),
129
- :ssl_client_key => OpenSSL::PKey::RSA.new(File.read("key.pem"), "passphrase, if any"),
130
- :ssl_ca_file => "ca_certificate.pem",
131
- :verify_ssl => OpenSSL::SSL::VERIFY_PEER
132
- ).get
133
-
134
- Self-signed certificates can be generated with the openssl command-line tool.
135
-
136
124
  == Meta
137
125
 
138
126
  Written by Adam Wiggins (adam at heroku dot com)
@@ -140,8 +128,7 @@ Written by Adam Wiggins (adam at heroku dot com)
140
128
  Patches contributed by: Chris Anderson, Greg Borenstein, Ardekantur, Pedro
141
129
  Belo, Rafael Souza, Rick Olson, Aman Gupta, Blake Mizerany, Brian Donovan, Ivan
142
130
  Makfinsky, Marc-André Cournoyer, Coda Hale, Tetsuo Watanabe, Dusty Doris,
143
- Lennon Day-Reynolds, James Edward Gray II, Cyril Rohr, Juan Alvarez, and Adam
144
- Jacob
131
+ Lennon Day-Reynolds, James Edward Gray II, Cyril Rohr, and Juan Alvarez
145
132
 
146
133
  Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
147
134
 
data/lib/restclient.rb CHANGED
@@ -4,9 +4,7 @@ require 'zlib'
4
4
  require 'stringio'
5
5
 
6
6
  require File.dirname(__FILE__) + '/restclient/request'
7
- require File.dirname(__FILE__) + '/restclient/mixin/response'
8
7
  require File.dirname(__FILE__) + '/restclient/response'
9
- require File.dirname(__FILE__) + '/restclient/raw_response'
10
8
  require File.dirname(__FILE__) + '/restclient/resource'
11
9
  require File.dirname(__FILE__) + '/restclient/exceptions'
12
10
 
@@ -1,17 +1,12 @@
1
- require 'tempfile'
2
-
3
1
  module RestClient
4
2
  # This class is used internally by RestClient to send the request, but you can also
5
3
  # access it internally if you'd like to use a method not directly supported by the
6
4
  # main API. For example:
7
5
  #
8
6
  # RestClient::Request.execute(:method => :head, :url => 'http://example.com')
9
- #
7
+ #
10
8
  class Request
11
- attr_reader :method, :url, :payload, :headers,
12
- :cookies, :user, :password, :timeout, :open_timeout,
13
- :verify_ssl, :ssl_client_cert, :ssl_client_key, :ssl_ca_file,
14
- :raw_response
9
+ attr_reader :method, :url, :payload, :headers, :cookies, :user, :password, :timeout, :open_timeout
15
10
 
16
11
  def self.execute(args)
17
12
  new(args).execute
@@ -21,18 +16,12 @@ module RestClient
21
16
  @method = args[:method] or raise ArgumentError, "must pass :method"
22
17
  @url = args[:url] or raise ArgumentError, "must pass :url"
23
18
  @headers = args[:headers] || {}
24
- @cookies = @headers.delete(:cookies) || args[:cookies] || {}
19
+ @cookies = @headers.delete(:cookies) || args[:cookies] || {}
25
20
  @payload = process_payload(args[:payload])
26
21
  @user = args[:user]
27
22
  @password = args[:password]
28
23
  @timeout = args[:timeout]
29
24
  @open_timeout = args[:open_timeout]
30
- @raw_response = args[:raw_response] || false
31
- @verify_ssl = args[:verify_ssl] || false
32
- @ssl_client_cert = args[:ssl_client_cert] || nil
33
- @ssl_client_key = args[:ssl_client_key] || nil
34
- @ssl_ca_file = args[:ssl_ca_file] || nil
35
- @tf = nil # If you are a raw request, this is your tempfile
36
25
  end
37
26
 
38
27
  def execute
@@ -48,13 +37,13 @@ module RestClient
48
37
  end
49
38
 
50
39
  def make_headers(user_headers)
51
- unless @cookies.empty?
52
- user_headers[:cookie] = @cookies.map {|key, val| "#{key.to_s}=#{val}" }.join('; ')
53
- end
40
+ unless @cookies.empty?
41
+ user_headers[:cookie] = @cookies.map {|key, val| "#{key.to_s}=#{val}" }.join('; ')
42
+ end
54
43
 
55
44
  default_headers.merge(user_headers).inject({}) do |final, (key, value)|
56
45
  final[key.to_s.gsub(/_/, '-').capitalize] = value.to_s
57
- final
46
+ final
58
47
  end
59
48
  end
60
49
 
@@ -112,24 +101,19 @@ module RestClient
112
101
 
113
102
  net = net_http_class.new(uri.host, uri.port)
114
103
  net.use_ssl = uri.is_a?(URI::HTTPS)
115
- net.verify_mode = OpenSSL::SSL::VERIFY_NONE if @verify_ssl == false
116
- net.cert = @ssl_client_cert if @ssl_client_cert
117
- net.key = @ssl_client_key if @ssl_client_key
118
- net.ca_file = @ssl_ca_file if @ssl_ca_file
104
+ net.verify_mode = OpenSSL::SSL::VERIFY_NONE
119
105
  net.read_timeout = @timeout if @timeout
120
106
  net.open_timeout = @open_timeout if @open_timeout
121
107
 
122
108
  display_log request_log
123
109
 
124
110
  net.start do |http|
125
- res = http.request(req, payload) { |http_response| fetch_body(http_response) }
126
- result = process_result(res)
111
+ res = http.request(req, payload)
127
112
  display_log response_log(res)
113
+ string = process_result(res)
128
114
 
129
- if result.kind_of?(String) or @method == :head
130
- Response.new(result, res)
131
- elsif @raw_response
132
- RawResponse.new(@tf, res)
115
+ if string or @method == :head
116
+ Response.new(string, res)
133
117
  else
134
118
  nil
135
119
  end
@@ -144,38 +128,9 @@ module RestClient
144
128
  req.basic_auth(user, password) if user
145
129
  end
146
130
 
147
- def fetch_body(http_response)
148
- if @raw_response
149
- # Taken from Chef, which as in turn...
150
- # Stolen from http://www.ruby-forum.com/topic/166423
151
- # Kudos to _why!
152
- @tf = Tempfile.new("rest-client")
153
- size, total = 0, http_response.header['Content-Length'].to_i
154
- http_response.read_body do |chunk|
155
- @tf.write(chunk)
156
- size += chunk.size
157
- if size == 0
158
- display_log("#{@method} #{@url} done (0 length file)")
159
- elsif total == 0
160
- display_log("#{@method} #{@url} (zero content length)")
161
- else
162
- display_log("#{@method} #{@url} %d%% done (%d of %d)" % [(size * 100) / total, size, total])
163
- end
164
- end
165
- @tf.close
166
- @tf
167
- else
168
- http_response.read_body
169
- end
170
- http_response
171
- end
172
-
173
131
  def process_result(res)
174
- if res.code =~ /\A2\d{2}\z/
175
- # We don't decode raw requests
176
- unless @raw_response
177
- decode res['content-encoding'], res.body if res.body
178
- end
132
+ if res.code =~ /\A2\d{2}\z/
133
+ decode res['content-encoding'], res.body if res.body
179
134
  elsif %w(301 302 303).include? res.code
180
135
  url = res.header['Location']
181
136
 
@@ -216,8 +171,7 @@ module RestClient
216
171
  end
217
172
 
218
173
  def response_log(res)
219
- size = @raw_response ? File.size(@tf.path) : res.body.size
220
- "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes"
174
+ "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{(res.body) ? res.body.size : nil} bytes"
221
175
  end
222
176
 
223
177
  def display_log(msg)
@@ -100,8 +100,8 @@ module RestClient
100
100
  end
101
101
 
102
102
  def open_timeout
103
- options[:open_timeout]
104
- end
103
+ options[:open_timeout]
104
+ end
105
105
 
106
106
  # Construct a subresource, preserving authentication.
107
107
  #
@@ -1,5 +1,3 @@
1
- require File.dirname(__FILE__) + '/mixin/response'
2
-
3
1
  module RestClient
4
2
  # The response from RestClient looks like a string, but is actually one of
5
3
  # these. 99% of the time you're making a rest call all you care about is
@@ -8,13 +6,41 @@ module RestClient
8
6
  # RestClient.get('http://example.com').headers[:content_type]
9
7
  #
10
8
  class Response < String
11
-
12
- include RestClient::Mixin::Response
9
+ attr_reader :net_http_res
13
10
 
14
11
  def initialize(string, net_http_res)
15
12
  @net_http_res = net_http_res
16
13
  super(string || "")
17
14
  end
18
15
 
16
+ # HTTP status code, always 200 since RestClient throws exceptions for
17
+ # other codes.
18
+ def code
19
+ @code ||= @net_http_res.code.to_i
20
+ end
21
+
22
+ # A hash of the headers, beautified with symbols and underscores.
23
+ # e.g. "Content-type" will become :content_type.
24
+ def headers
25
+ @headers ||= self.class.beautify_headers(@net_http_res.to_hash)
26
+ end
27
+
28
+ # Hash of cookies extracted from response headers
29
+ def cookies
30
+ @cookies ||= (self.headers[:set_cookie] || "").split('; ').inject({}) do |out, raw_c|
31
+ key, val = raw_c.split('=')
32
+ unless %w(expires domain path secure).member?(key)
33
+ out[key] = val
34
+ end
35
+ out
36
+ end
37
+ end
38
+
39
+ def self.beautify_headers(headers)
40
+ headers.inject({}) do |out, (key, value)|
41
+ out[key.gsub(/-/, '_').to_sym] = value.first
42
+ out
43
+ end
44
+ end
19
45
  end
20
46
  end
data/rest-client.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "rest-client"
3
- s.version = "0.9.3"
3
+ s.version = "0.9.3.1"
4
4
  s.summary = "Simple REST client for Ruby, inspired by microframework syntax for specifying actions."
5
5
  s.description = "A simple REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete."
6
6
  s.author = "Ian Steel"
data/spec/request_spec.rb CHANGED
@@ -28,7 +28,7 @@ describe RestClient::Request do
28
28
  it "decodes a gzip body" do
29
29
  @request.decode('gzip', "\037\213\b\b\006'\252H\000\003t\000\313T\317UH\257\312,HM\341\002\000G\242(\r\v\000\000\000").should == "i'm gziped\n"
30
30
  end
31
-
31
+
32
32
  it "ingores gzip for empty bodies" do
33
33
  @request.decode('gzip', '').should be_empty
34
34
  end
@@ -37,23 +37,23 @@ describe RestClient::Request do
37
37
  @request.decode('deflate', "x\234+\316\317MUHIM\313I,IMQ(I\255(\001\000A\223\006\363").should == "some deflated text"
38
38
  end
39
39
 
40
- it "processes a successful result" do
41
- res = mock("result")
42
- res.stub!(:code).and_return("200")
43
- res.stub!(:body).and_return('body')
44
- res.stub!(:[]).with('content-encoding').and_return(nil)
45
- @request.process_result(res).should == 'body'
46
- end
47
-
48
- it "doesn't classify successful requests as failed" do
49
- 203.upto(206) do |code|
50
- res = mock("result")
51
- res.stub!(:code).and_return(code.to_s)
52
- res.stub!(:body).and_return("")
53
- res.stub!(:[]).with('content-encoding').and_return(nil)
54
- @request.process_result(res).should be_empty
55
- end
56
- end
40
+ it "processes a successful result" do
41
+ res = mock("result")
42
+ res.stub!(:code).and_return("200")
43
+ res.stub!(:body).and_return('body')
44
+ res.stub!(:[]).with('content-encoding').and_return(nil)
45
+ @request.process_result(res).should == 'body'
46
+ end
47
+
48
+ it "doesn't classify successful requests as failed" do
49
+ 203.upto(206) do |code|
50
+ res = mock("result")
51
+ res.stub!(:code).and_return(code.to_s)
52
+ res.stub!(:body).and_return("")
53
+ res.stub!(:[]).with('content-encoding').and_return(nil)
54
+ @request.process_result(res).should be_empty
55
+ end
56
+ end
57
57
 
58
58
  it "parses a url into a URI object" do
59
59
  URI.should_receive(:parse).with('http://example.com/resource')
@@ -80,12 +80,12 @@ describe RestClient::Request do
80
80
  @request.password.should == 'pass2'
81
81
  end
82
82
 
83
- it "correctly formats cookies provided to the constructor" do
84
- URI.stub!(:parse).and_return(mock('uri', :user => nil, :password => nil))
85
- @request = RestClient::Request.new(:method => 'get', :url => 'example.com', :cookies => {:session_id => '1' })
86
- @request.should_receive(:default_headers).and_return({'foo' => 'bar'})
87
- headers = @request.make_headers({}).should == { 'Foo' => 'bar', 'Cookie' => 'session_id=1'}
88
- end
83
+ it "correctly formats cookies provided to the constructor" do
84
+ URI.stub!(:parse).and_return(mock('uri', :user => nil, :password => nil))
85
+ @request = RestClient::Request.new(:method => 'get', :url => 'example.com', :cookies => {:session_id => '1' })
86
+ @request.should_receive(:default_headers).and_return({'foo' => 'bar'})
87
+ headers = @request.make_headers({}).should == { 'Foo' => 'bar', 'Cookie' => 'session_id=1'}
88
+ end
89
89
 
90
90
  it "determines the Net::HTTP class to instantiate by the method name" do
91
91
  @request.net_http_request_class(:put).should == Net::HTTP::Put
@@ -243,7 +243,7 @@ describe RestClient::Request do
243
243
  end
244
244
 
245
245
  it "creates a non-proxy class if a proxy url is not given" do
246
- @request.net_http_class.should_not include(Net::HTTP::ProxyDelta)
246
+ @request.net_http_class.should_not include(Net::HTTP::ProxyDelta)
247
247
  end
248
248
 
249
249
  it "logs a get request" do
@@ -303,140 +303,26 @@ describe RestClient::Request do
303
303
  f.should_receive(:puts).with('xyz')
304
304
  @request.display_log('xyz')
305
305
  end
306
-
306
+
307
307
  it "set read_timeout" do
308
308
  @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :timeout => 123)
309
309
  @http.stub!(:request)
310
310
  @request.stub!(:process_result)
311
311
  @request.stub!(:response_log)
312
-
312
+
313
313
  @net.should_receive(:read_timeout=).with(123)
314
-
314
+
315
315
  @request.transmit(@uri, 'req', nil)
316
316
  end
317
-
317
+
318
318
  it "set open_timeout" do
319
319
  @request = RestClient::Request.new(:method => :put, :url => 'http://some/resource', :payload => 'payload', :open_timeout => 123)
320
320
  @http.stub!(:request)
321
321
  @request.stub!(:process_result)
322
322
  @request.stub!(:response_log)
323
-
323
+
324
324
  @net.should_receive(:open_timeout=).with(123)
325
-
325
+
326
326
  @request.transmit(@uri, 'req', nil)
327
327
  end
328
-
329
- it "should default to not verifying ssl certificates" do
330
- @request.verify_ssl.should == false
331
- end
332
-
333
- it "should set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is false" do
334
- @net.should_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
335
- @http.stub!(:request)
336
- @request.stub!(:process_result)
337
- @request.stub!(:response_log)
338
- @request.transmit(@uri, 'req', 'payload')
339
- end
340
-
341
- it "should not set net.verify_mode to OpenSSL::SSL::VERIFY_NONE if verify_ssl is true" do
342
- @request = RestClient::Request.new(:method => :put, :url => 'https://some/resource', :payload => 'payload', :verify_ssl => true)
343
- @net.should_not_receive(:verify_mode=).with(OpenSSL::SSL::VERIFY_NONE)
344
- @http.stub!(:request)
345
- @request.stub!(:process_result)
346
- @request.stub!(:response_log)
347
- @request.transmit(@uri, 'req', 'payload')
348
- end
349
-
350
- it "should default to not having an ssl_client_cert" do
351
- @request.ssl_client_cert.should be(nil)
352
- end
353
-
354
- it "should set the ssl_client_cert if provided" do
355
- @request = RestClient::Request.new(
356
- :method => :put,
357
- :url => 'https://some/resource',
358
- :payload => 'payload',
359
- :ssl_client_cert => "whatsupdoc!"
360
- )
361
- @net.should_receive(:cert=).with("whatsupdoc!")
362
- @http.stub!(:request)
363
- @request.stub!(:process_result)
364
- @request.stub!(:response_log)
365
- @request.transmit(@uri, 'req', 'payload')
366
- end
367
-
368
- it "should not set the ssl_client_cert if it is not provided" do
369
- @request = RestClient::Request.new(
370
- :method => :put,
371
- :url => 'https://some/resource',
372
- :payload => 'payload'
373
- )
374
- @net.should_not_receive(:cert=).with("whatsupdoc!")
375
- @http.stub!(:request)
376
- @request.stub!(:process_result)
377
- @request.stub!(:response_log)
378
- @request.transmit(@uri, 'req', 'payload')
379
- end
380
-
381
- it "should default to not having an ssl_client_key" do
382
- @request.ssl_client_key.should be(nil)
383
- end
384
-
385
- it "should set the ssl_client_key if provided" do
386
- @request = RestClient::Request.new(
387
- :method => :put,
388
- :url => 'https://some/resource',
389
- :payload => 'payload',
390
- :ssl_client_key => "whatsupdoc!"
391
- )
392
- @net.should_receive(:key=).with("whatsupdoc!")
393
- @http.stub!(:request)
394
- @request.stub!(:process_result)
395
- @request.stub!(:response_log)
396
- @request.transmit(@uri, 'req', 'payload')
397
- end
398
-
399
- it "should not set the ssl_client_key if it is not provided" do
400
- @request = RestClient::Request.new(
401
- :method => :put,
402
- :url => 'https://some/resource',
403
- :payload => 'payload'
404
- )
405
- @net.should_not_receive(:key=).with("whatsupdoc!")
406
- @http.stub!(:request)
407
- @request.stub!(:process_result)
408
- @request.stub!(:response_log)
409
- @request.transmit(@uri, 'req', 'payload')
410
- end
411
-
412
- it "should default to not having an ssl_ca_file" do
413
- @request.ssl_ca_file.should be(nil)
414
- end
415
-
416
- it "should set the ssl_ca_file if provided" do
417
- @request = RestClient::Request.new(
418
- :method => :put,
419
- :url => 'https://some/resource',
420
- :payload => 'payload',
421
- :ssl_ca_file => "Certificate Authority File"
422
- )
423
- @net.should_receive(:ca_file=).with("Certificate Authority File")
424
- @http.stub!(:request)
425
- @request.stub!(:process_result)
426
- @request.stub!(:response_log)
427
- @request.transmit(@uri, 'req', 'payload')
428
- end
429
-
430
- it "should not set the ssl_ca_file if it is not provided" do
431
- @request = RestClient::Request.new(
432
- :method => :put,
433
- :url => 'https://some/resource',
434
- :payload => 'payload'
435
- )
436
- @net.should_not_receive(:ca_file=).with("Certificate Authority File")
437
- @http.stub!(:request)
438
- @request.stub!(:process_result)
439
- @request.stub!(:response_log)
440
- @request.transmit(@uri, 'req', 'payload')
441
- end
442
328
  end
@@ -10,6 +10,35 @@ describe RestClient::Response do
10
10
  @response.should == 'abc'
11
11
  end
12
12
 
13
+ it "fetches the numeric response code" do
14
+ @net_http_res.should_receive(:code).and_return('200')
15
+ @response.code.should == 200
16
+ end
17
+
18
+ it "beautifies the headers by turning the keys to symbols" do
19
+ h = RestClient::Response.beautify_headers('content-type' => [ 'x' ])
20
+ h.keys.first.should == :content_type
21
+ end
22
+
23
+ it "beautifies the headers by turning the values to strings instead of one-element arrays" do
24
+ h = RestClient::Response.beautify_headers('x' => [ 'text/html' ] )
25
+ h.values.first.should == 'text/html'
26
+ end
27
+
28
+ it "fetches the headers" do
29
+ @net_http_res.should_receive(:to_hash).and_return('content-type' => [ 'text/html' ])
30
+ @response.headers.should == { :content_type => 'text/html' }
31
+ end
32
+
33
+ it "extracts cookies from response headers" do
34
+ @net_http_res.should_receive(:to_hash).and_return('set-cookie' => ['session_id=1; path=/'])
35
+ @response.cookies.should == { 'session_id' => '1' }
36
+ end
37
+
38
+ it "can access the net http result directly" do
39
+ @response.net_http_res.should == @net_http_res
40
+ end
41
+
13
42
  it "accepts nil strings and sets it to empty for the case of HEAD" do
14
43
  RestClient::Response.new(nil, @net_http_res).should == ""
15
44
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: isteel-rest-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.3
4
+ version: 0.9.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ian Steel