esod-client 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/VERSION +1 -1
  2. data/command_line_options.rb +3 -6
  3. data/esod-client.gemspec +29 -27
  4. data/lib/esod_client/esod_client.rb +2 -2
  5. data/lib/rest-client-1.4.2/README.rdoc +243 -0
  6. data/lib/rest-client-1.4.2/Rakefile +60 -0
  7. data/lib/rest-client-1.4.2/VERSION +1 -0
  8. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/bin/restclient +0 -0
  9. data/lib/rest-client-1.4.2/history.md +54 -0
  10. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/rest_client.rb +0 -0
  11. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient.rb +77 -21
  12. data/lib/rest-client-1.4.2/lib/restclient/abstract_response.rb +87 -0
  13. data/lib/rest-client-1.4.2/lib/restclient/exceptions.rb +146 -0
  14. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/net_http_ext.rb +0 -0
  15. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/payload.rb +15 -12
  16. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/raw_response.rb +7 -6
  17. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/request.rb +61 -89
  18. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/resource.rb +11 -10
  19. data/lib/rest-client-1.4.2/lib/restclient/response.rb +46 -0
  20. data/lib/{rest-client-1.2.0/spec/mixin/response_spec.rb → rest-client-1.4.2/spec/abstract_response_spec.rb} +3 -12
  21. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/base.rb +0 -0
  22. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/exceptions_spec.rb +23 -9
  23. data/lib/rest-client-1.4.2/spec/integration_spec.rb +38 -0
  24. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/master_shake.jpg +0 -0
  25. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/payload_spec.rb +20 -6
  26. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/raw_response_spec.rb +1 -1
  27. data/lib/rest-client-1.4.2/spec/request_spec.rb +518 -0
  28. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/resource_spec.rb +24 -0
  29. data/lib/rest-client-1.4.2/spec/response_spec.rb +130 -0
  30. data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/restclient_spec.rb +21 -11
  31. metadata +38 -29
  32. data/lib/rest-client-1.2.0/README.rdoc +0 -102
  33. data/lib/rest-client-1.2.0/Rakefile +0 -57
  34. data/lib/rest-client-1.2.0/VERSION +0 -1
  35. data/lib/rest-client-1.2.0/lib/restclient/exceptions.rb +0 -89
  36. data/lib/rest-client-1.2.0/lib/restclient/mixin/response.rb +0 -48
  37. data/lib/rest-client-1.2.0/lib/restclient/response.rb +0 -20
  38. data/lib/rest-client-1.2.0/spec/request_spec.rb +0 -521
  39. data/lib/rest-client-1.2.0/spec/response_spec.rb +0 -21
@@ -20,16 +20,17 @@ module RestClient
20
20
  # * :timeout and :open_timeout
21
21
  # * :ssl_client_cert, :ssl_client_key, :ssl_ca_file
22
22
  class Request
23
- attr_reader :method, :url, :payload, :headers, :processed_headers,
24
- :cookies, :user, :password, :timeout, :open_timeout,
25
- :verify_ssl, :ssl_client_cert, :ssl_client_key, :ssl_ca_file,
26
- :raw_response
27
23
 
28
- def self.execute(args)
29
- new(args).execute
24
+ attr_reader :method, :url, :headers, :cookies,
25
+ :payload, :user, :password, :timeout,
26
+ :open_timeout, :raw_response, :verify_ssl, :ssl_client_cert,
27
+ :ssl_client_key, :ssl_ca_file, :processed_headers, :args
28
+
29
+ def self.execute(args, &block)
30
+ new(args).execute &block
30
31
  end
31
32
 
32
- def initialize(args)
33
+ def initialize args
33
34
  @method = args[:method] or raise ArgumentError, "must pass :method"
34
35
  @url = args[:url] or raise ArgumentError, "must pass :url"
35
36
  @headers = args[:headers] || {}
@@ -46,25 +47,17 @@ module RestClient
46
47
  @ssl_ca_file = args[:ssl_ca_file] || nil
47
48
  @tf = nil # If you are a raw request, this is your tempfile
48
49
  @processed_headers = make_headers headers
50
+ @args = args
49
51
  end
50
52
 
51
- def execute
52
- execute_inner
53
- rescue Redirect => e
54
- @url = e.url
55
- @method = :get
56
- @payload = nil
57
- execute
58
- end
59
-
60
- def execute_inner
53
+ def execute &block
61
54
  uri = parse_url_with_auth(url)
62
- transmit uri, net_http_request_class(method).new(uri.request_uri, processed_headers), payload
55
+ transmit uri, net_http_request_class(method).new(uri.request_uri, processed_headers), payload, &block
63
56
  end
64
57
 
65
58
  def make_headers user_headers
66
59
  unless @cookies.empty?
67
- user_headers[:cookie] = @cookies.map {|key, val| "#{key.to_s}=#{val}" }.join('; ')
60
+ user_headers[:cookie] = @cookies.map {|(key, val)| "#{key.to_s}=#{val}" }.sort.join(",")
68
61
  end
69
62
 
70
63
  headers = default_headers.merge(user_headers).inject({}) do |final, (key, value)|
@@ -73,13 +66,13 @@ module RestClient
73
66
  target_value = value.to_s
74
67
  final[target_key] = MIME::Types.type_for_extension target_value
75
68
  elsif 'ACCEPT' == target_key.upcase
76
- # Accept can be composed of several comma-separated values
77
- if value.is_a? Array
78
- target_values = value
79
- else
80
- target_values = value.to_s.split ','
81
- end
82
- final[target_key] = target_values.map{ |ext| MIME::Types.type_for_extension(ext.to_s.strip)}.join(', ')
69
+ # Accept can be composed of several comma-separated values
70
+ if value.is_a? Array
71
+ target_values = value
72
+ else
73
+ target_values = value.to_s.split ','
74
+ end
75
+ final[target_key] = target_values.map{ |ext| MIME::Types.type_for_extension(ext.to_s.strip)}.join(', ')
83
76
  else
84
77
  final[target_key] = value.to_s
85
78
  end
@@ -132,8 +125,8 @@ module RestClient
132
125
  end
133
126
  end
134
127
 
135
- def transmit(uri, req, payload)
136
- setup_credentials(req)
128
+ def transmit uri, req, payload, &block
129
+ setup_credentials req
137
130
 
138
131
  net = net_http_class.new(uri.host, uri.port)
139
132
  net.use_ssl = uri.is_a?(URI::HTTPS)
@@ -148,20 +141,16 @@ module RestClient
148
141
  net.read_timeout = @timeout if @timeout
149
142
  net.open_timeout = @open_timeout if @open_timeout
150
143
 
151
- display_log request_log
144
+ RestClient.before_execution_procs.each do |before_proc|
145
+ before_proc.call(req, args)
146
+ end
147
+
148
+ log_request
152
149
 
153
150
  net.start do |http|
154
151
  res = http.request(req, payload) { |http_response| fetch_body(http_response) }
155
- result = process_result(res)
156
- display_log response_log(res)
157
-
158
- if result.kind_of?(String) or @method == :head
159
- Response.new(result, res)
160
- elsif @raw_response
161
- RawResponse.new(@tf, res)
162
- else
163
- Response.new(nil, res)
164
- end
152
+ log_response res
153
+ process_result res, &block
165
154
  end
166
155
  rescue EOFError
167
156
  raise RestClient::ServerBrokeConnection
@@ -181,14 +170,16 @@ module RestClient
181
170
  @tf = Tempfile.new("rest-client")
182
171
  size, total = 0, http_response.header['Content-Length'].to_i
183
172
  http_response.read_body do |chunk|
184
- @tf.write(chunk)
173
+ @tf.write chunk
185
174
  size += chunk.size
186
- if size == 0
187
- display_log("#{@method} #{@url} done (0 length file)")
188
- elsif total == 0
189
- display_log("#{@method} #{@url} (zero content length)")
190
- else
191
- display_log("#{@method} #{@url} %d%% done (%d of %d)" % [(size * 100) / total, size, total])
175
+ if RestClient.log
176
+ if size == 0
177
+ RestClient.log << "#{@method} #{@url} done (0 length file\n)"
178
+ elsif total == 0
179
+ RestClient.log << "#{@method} #{@url} (zero content length)\n"
180
+ else
181
+ RestClient.log << "#{@method} #{@url} %d%% done (%d of %d)\n" % [(size * 100) / total, size, total]
182
+ end
192
183
  end
193
184
  end
194
185
  @tf.close
@@ -199,67 +190,48 @@ module RestClient
199
190
  http_response
200
191
  end
201
192
 
202
- def process_result(res)
203
- if res.code =~ /\A2\d{2}\z/
193
+ def process_result res, &block
194
+ if @raw_response
204
195
  # We don't decode raw requests
205
- unless @raw_response
206
- self.class.decode res['content-encoding'], res.body if res.body
207
- end
208
- elsif %w(301 302 303).include? res.code
209
- url = res.header['Location']
210
-
211
- if url !~ /^http/
212
- uri = URI.parse(@url)
213
- uri.path = "/#{url}".squeeze('/')
214
- url = uri.to_s
215
- end
196
+ response = RawResponse.new(@tf, res, args)
197
+ else
198
+ response = Response.new(Request.decode(res['content-encoding'], res.body), res, args)
199
+ end
216
200
 
217
- raise Redirect, url
218
- elsif res.code == "304"
219
- raise NotModified, res
220
- elsif res.code == "401"
221
- raise Unauthorized, res
222
- elsif res.code == "404"
223
- raise ResourceNotFound, res
201
+ if block_given?
202
+ block.call response, &block
224
203
  else
225
- raise RequestFailed, res
204
+ response.return! &block
226
205
  end
206
+
227
207
  end
228
208
 
229
- def self.decode(content_encoding, body)
230
- if content_encoding == 'gzip' and not body.empty?
209
+ def self.decode content_encoding, body
210
+ if (!body) || body.empty?
211
+ body
212
+ elsif content_encoding == 'gzip'
231
213
  Zlib::GzipReader.new(StringIO.new(body)).read
232
214
  elsif content_encoding == 'deflate'
233
- Zlib::Inflate.new.inflate(body)
215
+ Zlib::Inflate.new.inflate body
234
216
  else
235
217
  body
236
218
  end
237
219
  end
238
220
 
239
- def request_log
221
+ def log_request
240
222
  if RestClient.log
241
223
  out = []
242
224
  out << "RestClient.#{method} #{url.inspect}"
243
- out << "headers: #{processed_headers.inspect}"
244
- out << "paylod: #{payload.short_inspect}" if payload
245
- out.join(', ')
225
+ out << payload.short_inspect if payload
226
+ out << processed_headers.inspect.gsub(/^\{/, '').gsub(/\}$/, '')
227
+ RestClient.log << out.join(', ') + "\n"
246
228
  end
247
229
  end
248
230
 
249
- def response_log(res)
250
- size = @raw_response ? File.size(@tf.path) : (res.body.nil? ? 0 : res.body.size)
251
- "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes"
252
- end
253
-
254
- def display_log(msg)
255
- return unless log_to = RestClient.log
256
-
257
- if log_to == 'stdout'
258
- STDOUT.puts msg
259
- elsif log_to == 'stderr'
260
- STDERR.puts msg
261
- else
262
- File.open(log_to, 'a') { |f| f.puts msg }
231
+ def log_response res
232
+ if RestClient.log
233
+ size = @raw_response ? File.size(@tf.path) : (res.body.nil? ? 0 : res.body.size)
234
+ RestClient.log << "# => #{res.code} #{res.class.to_s.gsub(/^Net::HTTP/, '')} | #{(res['Content-type'] || '').gsub(/;.*$/, '')} #{size} bytes\n"
263
235
  end
264
236
  end
265
237
 
@@ -274,7 +246,7 @@ module MIME
274
246
 
275
247
  # Return the first found content-type for a value considered as an extension or the value itself
276
248
  def type_for_extension ext
277
- candidates = @extension_index[ext]
249
+ candidates = @extension_index[ext]
278
250
  candidates.empty? ? ext : candidates[0].content_type
279
251
  end
280
252
 
@@ -34,10 +34,11 @@ module RestClient
34
34
  # site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
35
35
  #
36
36
  class Resource
37
- attr_reader :url, :options
37
+ attr_reader :url, :options, :block
38
38
 
39
- def initialize(url, options={}, backwards_compatibility=nil)
39
+ def initialize(url, options={}, backwards_compatibility=nil, &block)
40
40
  @url = url
41
+ @block = block
41
42
  if options.class == Hash
42
43
  @options = options
43
44
  else # compatibility with previous versions
@@ -45,38 +46,38 @@ module RestClient
45
46
  end
46
47
  end
47
48
 
48
- def get(additional_headers={}, &b)
49
+ def get(additional_headers={}, &block)
49
50
  headers = (options[:headers] || {}).merge(additional_headers)
50
51
  Request.execute(options.merge(
51
52
  :method => :get,
52
53
  :url => url,
53
- :headers => headers), &b)
54
+ :headers => headers), &(block || @block))
54
55
  end
55
56
 
56
- def post(payload, additional_headers={}, &b)
57
+ def post(payload, additional_headers={}, &block)
57
58
  headers = (options[:headers] || {}).merge(additional_headers)
58
59
  Request.execute(options.merge(
59
60
  :method => :post,
60
61
  :url => url,
61
62
  :payload => payload,
62
- :headers => headers), &b)
63
+ :headers => headers), &(block || @block))
63
64
  end
64
65
 
65
- def put(payload, additional_headers={}, &b)
66
+ def put(payload, additional_headers={}, &block)
66
67
  headers = (options[:headers] || {}).merge(additional_headers)
67
68
  Request.execute(options.merge(
68
69
  :method => :put,
69
70
  :url => url,
70
71
  :payload => payload,
71
- :headers => headers), &b)
72
+ :headers => headers), &(block || @block))
72
73
  end
73
74
 
74
- def delete(additional_headers={}, &b)
75
+ def delete(additional_headers={}, &block)
75
76
  headers = (options[:headers] || {}).merge(additional_headers)
76
77
  Request.execute(options.merge(
77
78
  :method => :delete,
78
79
  :url => url,
79
- :headers => headers), &b)
80
+ :headers => headers), &(block || @block))
80
81
  end
81
82
 
82
83
  def to_s
@@ -0,0 +1,46 @@
1
+ module RestClient
2
+
3
+ # A Response from RestClient, you can access the response body, the code or the headers.
4
+ #
5
+ class Response < AbstractResponse
6
+
7
+ attr_reader :body
8
+
9
+ WARNING_MESSAGE = '[warning] The Response is no more a String and the Response content is now accessed through Response.body, please update your code'
10
+
11
+ def initialize body, net_http_res, args
12
+ super net_http_res, args
13
+ @body = body || ""
14
+ end
15
+
16
+ def method_missing symbol, *args
17
+ if body.respond_to? symbol
18
+ warn WARNING_MESSAGE
19
+ body.send symbol, *args
20
+ else
21
+ super
22
+ end
23
+ end
24
+
25
+ def == o
26
+ if super
27
+ true
28
+ else
29
+ equal_body = (body == o)
30
+ if equal_body
31
+ warn WARNING_MESSAGE
32
+ end
33
+ equal_body
34
+ end
35
+ end
36
+
37
+ def to_s
38
+ body.to_s
39
+ end
40
+
41
+ def size
42
+ body.size
43
+ end
44
+
45
+ end
46
+ end
@@ -1,18 +1,9 @@
1
- require File.dirname(__FILE__) + '/../base'
1
+ require File.dirname(__FILE__) + '/base'
2
2
 
3
- class MockResponse
4
- include RestClient::Mixin::Response
5
-
6
- def initialize(body, res)
7
- @net_http_res = res
8
- @body = @body
9
- end
10
- end
11
-
12
- describe RestClient::Mixin::Response do
3
+ describe RestClient::AbstractResponse do
13
4
  before do
14
5
  @net_http_res = mock('net http response')
15
- @response = MockResponse.new('abc', @net_http_res)
6
+ @response = RestClient::AbstractResponse.new(@net_http_res, {})
16
7
  end
17
8
 
18
9
  it "fetches the numeric response code" do
@@ -1,8 +1,11 @@
1
1
  require File.dirname(__FILE__) + '/base'
2
2
 
3
+ require 'webmock/rspec'
4
+ include WebMock
5
+
3
6
  describe RestClient::Exception do
4
7
  it "sets the exception message to ErrorMessage" do
5
- RestClient::ResourceNotFound.new.message.should == 'Resource not found'
8
+ RestClient::ResourceNotFound.new.message.should == 'Resource Not Found'
6
9
  end
7
10
 
8
11
  it "contains exceptions in RestClient" do
@@ -17,10 +20,11 @@ describe RestClient::RequestFailed do
17
20
  end
18
21
 
19
22
  it "stores the http response on the exception" do
23
+ response = "response"
20
24
  begin
21
- raise RestClient::RequestFailed, :response
25
+ raise RestClient::RequestFailed, response
22
26
  rescue RestClient::RequestFailed => e
23
- e.response.should == :response
27
+ e.response.should == response
24
28
  end
25
29
  end
26
30
 
@@ -29,10 +33,8 @@ describe RestClient::RequestFailed do
29
33
  end
30
34
 
31
35
  it "http_body convenience method for fetching the body (decoding when necessary)" do
32
- @response.stub!(:[]).with('content-encoding').and_return('gzip')
33
- @response.stub!(:body).and_return('compressed body')
34
- RestClient::Request.should_receive(:decode).with('gzip', 'compressed body').and_return('plain body')
35
- RestClient::RequestFailed.new(@response).http_body.should == 'plain body'
36
+ RestClient::RequestFailed.new(@response).http_code.should == 502
37
+ RestClient::RequestFailed.new(@response).message.should == 'HTTP status code 502'
36
38
  end
37
39
 
38
40
  it "shows the status code in the message" do
@@ -42,10 +44,11 @@ end
42
44
 
43
45
  describe RestClient::ResourceNotFound do
44
46
  it "also has the http response attached" do
47
+ response = "response"
45
48
  begin
46
- raise RestClient::ResourceNotFound, :response
49
+ raise RestClient::ResourceNotFound, response
47
50
  rescue RestClient::ResourceNotFound => e
48
- e.response.should == :response
51
+ e.response.should == response
49
52
  end
50
53
  end
51
54
  end
@@ -62,4 +65,15 @@ describe "backwards compatibility" do
62
65
  it "alias RestClient::Request::RequestFailed to RestClient::RequestFailed" do
63
66
  RestClient::Request::RequestFailed.should == RestClient::RequestFailed
64
67
  end
68
+
69
+ it "make the exception's response act like an Net::HTTPResponse" do
70
+ body = "body"
71
+ stub_request(:get, "www.example.com").to_return(:body => body, :status => 404)
72
+ begin
73
+ RestClient.get "www.example.com"
74
+ raise
75
+ rescue RestClient::ResourceNotFound => e
76
+ e.response.body.should == body
77
+ end
78
+ end
65
79
  end
@@ -0,0 +1,38 @@
1
+ require File.dirname(__FILE__) + '/base'
2
+
3
+ require 'webmock/rspec'
4
+ include WebMock
5
+
6
+ describe RestClient do
7
+
8
+ it "a simple request" do
9
+ body = 'abc'
10
+ stub_request(:get, "www.example.com").to_return(:body => body, :status => 200)
11
+ response = RestClient.get "www.example.com"
12
+ response.code.should == 200
13
+ response.body.should == body
14
+ end
15
+
16
+ it "a simple request with gzipped content" do
17
+ stub_request(:get, "www.example.com").with(:headers => { 'Accept-Encoding' => 'gzip, deflate' }).to_return(:body => "\037\213\b\b\006'\252H\000\003t\000\313T\317UH\257\312,HM\341\002\000G\242(\r\v\000\000\000", :status => 200, :headers => { 'Content-Encoding' => 'gzip' } )
18
+ response = RestClient.get "www.example.com"
19
+ response.code.should == 200
20
+ response.body.should == "i'm gziped\n"
21
+ end
22
+
23
+ it "a 404" do
24
+ body = "Ho hai ! I'm not here !"
25
+ stub_request(:get, "www.example.com").to_return(:body => body, :status => 404)
26
+ begin
27
+ RestClient.get "www.example.com"
28
+ raise
29
+ rescue RestClient::ResourceNotFound => e
30
+ e.http_code.should == 404
31
+ e.response.code.should == 404
32
+ e.response.body.should == body
33
+ e.http_body.should == body
34
+ end
35
+ end
36
+
37
+
38
+ end