esod-client 0.2.1 → 0.3.0

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.
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