isteel-rest-client 0.9.3 → 0.9.3.1

Sign up to get free protection for your applications and to get access to all the features.
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