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.
- data/VERSION +1 -1
- data/command_line_options.rb +3 -6
- data/esod-client.gemspec +29 -27
- data/lib/esod_client/esod_client.rb +2 -2
- data/lib/rest-client-1.4.2/README.rdoc +243 -0
- data/lib/rest-client-1.4.2/Rakefile +60 -0
- data/lib/rest-client-1.4.2/VERSION +1 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/bin/restclient +0 -0
- data/lib/rest-client-1.4.2/history.md +54 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/rest_client.rb +0 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient.rb +77 -21
- data/lib/rest-client-1.4.2/lib/restclient/abstract_response.rb +87 -0
- data/lib/rest-client-1.4.2/lib/restclient/exceptions.rb +146 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/net_http_ext.rb +0 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/payload.rb +15 -12
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/raw_response.rb +7 -6
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/request.rb +61 -89
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/lib/restclient/resource.rb +11 -10
- data/lib/rest-client-1.4.2/lib/restclient/response.rb +46 -0
- data/lib/{rest-client-1.2.0/spec/mixin/response_spec.rb → rest-client-1.4.2/spec/abstract_response_spec.rb} +3 -12
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/base.rb +0 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/exceptions_spec.rb +23 -9
- data/lib/rest-client-1.4.2/spec/integration_spec.rb +38 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/master_shake.jpg +0 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/payload_spec.rb +20 -6
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/raw_response_spec.rb +1 -1
- data/lib/rest-client-1.4.2/spec/request_spec.rb +518 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/resource_spec.rb +24 -0
- data/lib/rest-client-1.4.2/spec/response_spec.rb +130 -0
- data/lib/{rest-client-1.2.0 → rest-client-1.4.2}/spec/restclient_spec.rb +21 -11
- metadata +38 -29
- data/lib/rest-client-1.2.0/README.rdoc +0 -102
- data/lib/rest-client-1.2.0/Rakefile +0 -57
- data/lib/rest-client-1.2.0/VERSION +0 -1
- data/lib/rest-client-1.2.0/lib/restclient/exceptions.rb +0 -89
- data/lib/rest-client-1.2.0/lib/restclient/mixin/response.rb +0 -48
- data/lib/rest-client-1.2.0/lib/restclient/response.rb +0 -20
- data/lib/rest-client-1.2.0/spec/request_spec.rb +0 -521
- 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
|
-
|
29
|
-
|
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
|
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
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
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
|
136
|
-
setup_credentials
|
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
|
-
|
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
|
-
|
156
|
-
|
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
|
173
|
+
@tf.write chunk
|
185
174
|
size += chunk.size
|
186
|
-
if
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
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
|
203
|
-
if
|
193
|
+
def process_result res, &block
|
194
|
+
if @raw_response
|
204
195
|
# We don't decode raw requests
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
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
|
-
|
218
|
-
|
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
|
-
|
204
|
+
response.return! &block
|
226
205
|
end
|
206
|
+
|
227
207
|
end
|
228
208
|
|
229
|
-
def self.decode
|
230
|
-
if
|
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
|
215
|
+
Zlib::Inflate.new.inflate body
|
234
216
|
else
|
235
217
|
body
|
236
218
|
end
|
237
219
|
end
|
238
220
|
|
239
|
-
def
|
221
|
+
def log_request
|
240
222
|
if RestClient.log
|
241
223
|
out = []
|
242
224
|
out << "RestClient.#{method} #{url.inspect}"
|
243
|
-
out <<
|
244
|
-
out <<
|
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
|
250
|
-
|
251
|
-
|
252
|
-
|
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 =
|
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={}, &
|
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), &
|
54
|
+
:headers => headers), &(block || @block))
|
54
55
|
end
|
55
56
|
|
56
|
-
def post(payload, additional_headers={}, &
|
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), &
|
63
|
+
:headers => headers), &(block || @block))
|
63
64
|
end
|
64
65
|
|
65
|
-
def put(payload, additional_headers={}, &
|
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), &
|
72
|
+
:headers => headers), &(block || @block))
|
72
73
|
end
|
73
74
|
|
74
|
-
def delete(additional_headers={}, &
|
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), &
|
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__) + '
|
1
|
+
require File.dirname(__FILE__) + '/base'
|
2
2
|
|
3
|
-
|
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 =
|
6
|
+
@response = RestClient::AbstractResponse.new(@net_http_res, {})
|
16
7
|
end
|
17
8
|
|
18
9
|
it "fetches the numeric response code" do
|
File without changes
|
@@ -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
|
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,
|
25
|
+
raise RestClient::RequestFailed, response
|
22
26
|
rescue RestClient::RequestFailed => e
|
23
|
-
e.response.should ==
|
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
|
33
|
-
@response
|
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,
|
49
|
+
raise RestClient::ResourceNotFound, response
|
47
50
|
rescue RestClient::ResourceNotFound => e
|
48
|
-
e.response.should ==
|
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
|