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