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
File without changes
|
@@ -9,12 +9,12 @@ rescue LoadError => e
|
|
9
9
|
raise LoadError, "no such file to load -- net/https. Try running apt-get install libopenssl-ruby"
|
10
10
|
end
|
11
11
|
|
12
|
+
require File.dirname(__FILE__) + '/restclient/exceptions'
|
12
13
|
require File.dirname(__FILE__) + '/restclient/request'
|
13
|
-
require File.dirname(__FILE__) + '/restclient/
|
14
|
+
require File.dirname(__FILE__) + '/restclient/abstract_response'
|
14
15
|
require File.dirname(__FILE__) + '/restclient/response'
|
15
16
|
require File.dirname(__FILE__) + '/restclient/raw_response'
|
16
17
|
require File.dirname(__FILE__) + '/restclient/resource'
|
17
|
-
require File.dirname(__FILE__) + '/restclient/exceptions'
|
18
18
|
require File.dirname(__FILE__) + '/restclient/payload'
|
19
19
|
require File.dirname(__FILE__) + '/restclient/net_http_ext'
|
20
20
|
|
@@ -64,40 +64,38 @@ require File.dirname(__FILE__) + '/restclient/net_http_ext'
|
|
64
64
|
#
|
65
65
|
module RestClient
|
66
66
|
|
67
|
-
def self.get(url, headers={})
|
68
|
-
Request.execute(:method => :get, :url => url, :headers => headers)
|
67
|
+
def self.get(url, headers={}, &block)
|
68
|
+
Request.execute(:method => :get, :url => url, :headers => headers, &block)
|
69
69
|
end
|
70
70
|
|
71
|
-
def self.post(url, payload, headers={})
|
72
|
-
Request.execute(:method => :post, :url => url, :payload => payload, :headers => headers)
|
71
|
+
def self.post(url, payload, headers={}, &block)
|
72
|
+
Request.execute(:method => :post, :url => url, :payload => payload, :headers => headers, &block)
|
73
73
|
end
|
74
74
|
|
75
|
-
def self.put(url, payload, headers={})
|
76
|
-
Request.execute(:method => :put, :url => url, :payload => payload, :headers => headers)
|
75
|
+
def self.put(url, payload, headers={}, &block)
|
76
|
+
Request.execute(:method => :put, :url => url, :payload => payload, :headers => headers, &block)
|
77
77
|
end
|
78
78
|
|
79
|
-
def self.delete(url, headers={})
|
80
|
-
Request.execute(:method => :delete, :url => url, :headers => headers)
|
79
|
+
def self.delete(url, headers={}, &block)
|
80
|
+
Request.execute(:method => :delete, :url => url, :headers => headers, &block)
|
81
81
|
end
|
82
82
|
|
83
|
-
def self.head(url, headers={})
|
84
|
-
Request.execute(:method => :head, :url => url, :headers => headers)
|
83
|
+
def self.head(url, headers={}, &block)
|
84
|
+
Request.execute(:method => :head, :url => url, :headers => headers, &block)
|
85
85
|
end
|
86
86
|
|
87
87
|
class << self
|
88
88
|
attr_accessor :proxy
|
89
89
|
end
|
90
90
|
|
91
|
-
#
|
91
|
+
# Setup the log for RestClient calls.
|
92
|
+
# Value should be a logger but can can be stdout, stderr, or a filename.
|
92
93
|
# You can also configure logging by the environment variable RESTCLIENT_LOG.
|
93
|
-
def self.log=
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
return ENV['RESTCLIENT_LOG'] if ENV['RESTCLIENT_LOG']
|
99
|
-
return @@log if defined? @@log
|
100
|
-
nil
|
94
|
+
def self.log= log
|
95
|
+
if log.is_a? String
|
96
|
+
warn "[warning] You should set the log with a logger"
|
97
|
+
end
|
98
|
+
@@log = create_log log
|
101
99
|
end
|
102
100
|
|
103
101
|
def self.version
|
@@ -105,4 +103,62 @@ module RestClient
|
|
105
103
|
return File.read(version_path).chomp if File.file?(version_path)
|
106
104
|
"0.0.0"
|
107
105
|
end
|
106
|
+
|
107
|
+
# Create a log that respond to << like a logger
|
108
|
+
# param can be 'stdout', 'stderr', a string (then we will log to that file) or a logger (then we return it)
|
109
|
+
def self.create_log param
|
110
|
+
if param
|
111
|
+
if param.is_a? String
|
112
|
+
if param == 'stdout'
|
113
|
+
stdout_logger = Class.new do
|
114
|
+
def << obj
|
115
|
+
STDOUT.puts obj
|
116
|
+
end
|
117
|
+
end
|
118
|
+
stdout_logger.new
|
119
|
+
elsif param == 'stderr'
|
120
|
+
stderr_logger = Class.new do
|
121
|
+
def << obj
|
122
|
+
STDERR.puts obj
|
123
|
+
end
|
124
|
+
end
|
125
|
+
stderr_logger.new
|
126
|
+
else
|
127
|
+
file_logger = Class.new do
|
128
|
+
attr_writer :target_file
|
129
|
+
|
130
|
+
def << obj
|
131
|
+
File.open(@target_file, 'a') { |f| f.puts obj }
|
132
|
+
end
|
133
|
+
end
|
134
|
+
logger = file_logger.new
|
135
|
+
logger.target_file = param
|
136
|
+
logger
|
137
|
+
end
|
138
|
+
else
|
139
|
+
param
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
@@env_log = create_log ENV['RESTCLIENT_LOG']
|
145
|
+
|
146
|
+
@@log = nil
|
147
|
+
|
148
|
+
def self.log # :nodoc:
|
149
|
+
@@env_log || @@log
|
150
|
+
end
|
151
|
+
|
152
|
+
@@before_execution_procs = []
|
153
|
+
|
154
|
+
# Add a Proc to be called before each request in executed.
|
155
|
+
# The proc parameters will be the http request and the request params.
|
156
|
+
def self.add_before_execution_proc &proc
|
157
|
+
@@before_execution_procs << proc
|
158
|
+
end
|
159
|
+
|
160
|
+
def self.before_execution_procs # :nodoc:
|
161
|
+
@@before_execution_procs
|
162
|
+
end
|
163
|
+
|
108
164
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module RestClient
|
2
|
+
|
3
|
+
class AbstractResponse
|
4
|
+
|
5
|
+
attr_reader :net_http_res, :args
|
6
|
+
|
7
|
+
def initialize net_http_res, args
|
8
|
+
@net_http_res = net_http_res
|
9
|
+
@args = args
|
10
|
+
end
|
11
|
+
|
12
|
+
# HTTP status code
|
13
|
+
def code
|
14
|
+
@code ||= @net_http_res.code.to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
# A hash of the headers, beautified with symbols and underscores.
|
18
|
+
# e.g. "Content-type" will become :content_type.
|
19
|
+
def headers
|
20
|
+
@headers ||= self.class.beautify_headers(@net_http_res.to_hash)
|
21
|
+
end
|
22
|
+
|
23
|
+
# The raw headers.
|
24
|
+
def raw_headers
|
25
|
+
@raw_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] || []).inject({}) do |out, cookie_content|
|
31
|
+
# correctly parse comma-separated cookies containing HTTP dates (which also contain a comma)
|
32
|
+
cookie_content.split(/,\s*/).inject([""]) { |array, blob|
|
33
|
+
blob =~ /expires=.+?$/ ? array.push(blob) : array.last.concat(blob)
|
34
|
+
array
|
35
|
+
}.each do |cookie|
|
36
|
+
next if cookie.empty?
|
37
|
+
key, *val = cookie.split(";").first.split("=")
|
38
|
+
out[key] = val.join("=")
|
39
|
+
end
|
40
|
+
out
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Return the default behavior corresponding to the response code:
|
45
|
+
# the response itself for code in 200..206, redirection for 301 and 302 in get and head cases, redirection for 303 and an exception in other cases
|
46
|
+
def return! &block
|
47
|
+
if (200..206).include? code
|
48
|
+
self
|
49
|
+
elsif [301, 302].include? code
|
50
|
+
unless [:get, :head].include? args[:method]
|
51
|
+
raise Exceptions::EXCEPTIONS_MAP[code], self
|
52
|
+
else
|
53
|
+
follow_redirection &block
|
54
|
+
end
|
55
|
+
elsif code == 303
|
56
|
+
args[:method] = :get
|
57
|
+
args.delete :payload
|
58
|
+
follow_redirection &block
|
59
|
+
elsif Exceptions::EXCEPTIONS_MAP[code]
|
60
|
+
raise Exceptions::EXCEPTIONS_MAP[code], self
|
61
|
+
else
|
62
|
+
raise RequestFailed, self
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def inspect
|
67
|
+
"#{code} #{STATUSES[code]} | #{(headers[:content_type] || '').gsub(/;.*$/, '')} #{size} bytes\n"
|
68
|
+
end
|
69
|
+
|
70
|
+
# Follow a redirection
|
71
|
+
def follow_redirection &block
|
72
|
+
url = headers[:location]
|
73
|
+
if url !~ /^http/
|
74
|
+
url = URI.parse(args[:url]).merge(url).to_s
|
75
|
+
end
|
76
|
+
args[:url] = url
|
77
|
+
Request.execute args, &block
|
78
|
+
end
|
79
|
+
|
80
|
+
def AbstractResponse.beautify_headers(headers)
|
81
|
+
headers.inject({}) do |out, (key, value)|
|
82
|
+
out[key.gsub(/-/, '_').downcase.to_sym] = %w{set-cookie}.include?(key.downcase) ? value : value.first
|
83
|
+
out
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
module RestClient
|
2
|
+
|
3
|
+
STATUSES = {100 => 'Continue',
|
4
|
+
101 => 'Switching Protocols',
|
5
|
+
200 => 'OK',
|
6
|
+
201 => 'Created',
|
7
|
+
202 => 'Accepted',
|
8
|
+
203 => 'Non-Authoritative Information',
|
9
|
+
204 => 'No Content',
|
10
|
+
205 => 'Reset Content',
|
11
|
+
206 => 'Partial Content',
|
12
|
+
300 => 'Multiple Choices',
|
13
|
+
301 => 'Moved Permanently',
|
14
|
+
302 => 'Found',
|
15
|
+
303 => 'See Other',
|
16
|
+
304 => 'Not Modified',
|
17
|
+
305 => 'Use Proxy',
|
18
|
+
400 => 'Bad Request',
|
19
|
+
401 => 'Unauthorized',
|
20
|
+
403 => 'Forbidden',
|
21
|
+
404 => 'Resource Not Found',
|
22
|
+
405 => 'Method Not Allowed',
|
23
|
+
406 => 'Not Acceptable',
|
24
|
+
407 => 'Proxy Authentication Required',
|
25
|
+
408 => 'Request Timeout',
|
26
|
+
409 => 'Conflict',
|
27
|
+
410 => 'Gone',
|
28
|
+
411 => 'Length Required',
|
29
|
+
412 => 'Precondition Failed',
|
30
|
+
413 => 'Request Entity Too Large',
|
31
|
+
414 => 'Request-URI Too Long',
|
32
|
+
415 => 'Unsupported Media Type',
|
33
|
+
416 => 'Requested Range Not Satisfiable',
|
34
|
+
417 => 'Expectation Failed',
|
35
|
+
500 => 'Internal Server Error',
|
36
|
+
501 => 'Not Implemented',
|
37
|
+
502 => 'Bad Gateway',
|
38
|
+
503 => 'Service Unavailable',
|
39
|
+
504 => 'Gateway Timeout',
|
40
|
+
505 => 'HTTP Version Not Supported'}
|
41
|
+
|
42
|
+
# Compatibility : make the Response act like a Net::HTTPResponse when needed
|
43
|
+
module ResponseForException
|
44
|
+
def method_missing symbol, *args
|
45
|
+
if net_http_res.respond_to? symbol
|
46
|
+
warn "[warning] The response contained in an RestClient::Exception is now a RestClient::Response instead of a Net::HTTPResponse, please update your code"
|
47
|
+
net_http_res.send symbol, *args
|
48
|
+
else
|
49
|
+
super
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# This is the base RestClient exception class. Rescue it if you want to
|
55
|
+
# catch any exception that your request might raise
|
56
|
+
# You can get the status code by e.http_code, or see anything about the
|
57
|
+
# response via e.response.
|
58
|
+
# For example, the entire result body (which is
|
59
|
+
# probably an HTML error page) is e.response.
|
60
|
+
class Exception < RuntimeError
|
61
|
+
attr_accessor :message, :response
|
62
|
+
|
63
|
+
def initialize response = nil
|
64
|
+
@response = response
|
65
|
+
|
66
|
+
# compatibility: this make the exception behave like a Net::HTTPResponse
|
67
|
+
response.extend ResponseForException if response
|
68
|
+
end
|
69
|
+
|
70
|
+
def http_code
|
71
|
+
# return integer for compatibility
|
72
|
+
@response.code.to_i if @response
|
73
|
+
end
|
74
|
+
|
75
|
+
def http_body
|
76
|
+
@response.body
|
77
|
+
end
|
78
|
+
|
79
|
+
def inspect
|
80
|
+
"#{self.class} : #{http_code} #{message}"
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
# Compatibility
|
86
|
+
class ExceptionWithResponse < Exception
|
87
|
+
end
|
88
|
+
|
89
|
+
# The request failed with an error code not managed by the code
|
90
|
+
class RequestFailed < ExceptionWithResponse
|
91
|
+
|
92
|
+
def message
|
93
|
+
"HTTP status code #{http_code}"
|
94
|
+
end
|
95
|
+
|
96
|
+
def to_s
|
97
|
+
message
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# We will a create an exception for each status code, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
|
102
|
+
module Exceptions
|
103
|
+
# Map http status codes to the corresponding exception class
|
104
|
+
EXCEPTIONS_MAP = {}
|
105
|
+
end
|
106
|
+
|
107
|
+
STATUSES.each_pair do |code, message|
|
108
|
+
|
109
|
+
# Compatibility
|
110
|
+
superclass = ([304, 401, 404].include? code) ? ExceptionWithResponse : RequestFailed
|
111
|
+
klass = Class.new(superclass) do
|
112
|
+
send(:define_method, :message) {message}
|
113
|
+
end
|
114
|
+
klass_constant = const_set message.gsub(/ /, '').gsub(/-/, ''), klass
|
115
|
+
Exceptions::EXCEPTIONS_MAP[code] = klass_constant
|
116
|
+
end
|
117
|
+
|
118
|
+
# A redirect was encountered; caught by execute to retry with the new url.
|
119
|
+
class Redirect < Exception
|
120
|
+
|
121
|
+
message = 'Redirect'
|
122
|
+
|
123
|
+
attr_accessor :url
|
124
|
+
|
125
|
+
def initialize(url)
|
126
|
+
@url = url
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
# The server broke the connection prior to the request completing. Usually
|
131
|
+
# this means it crashed, or sometimes that your network connection was
|
132
|
+
# severed before it could complete.
|
133
|
+
class ServerBrokeConnection < Exception
|
134
|
+
message = 'Server broke connection'
|
135
|
+
end
|
136
|
+
|
137
|
+
|
138
|
+
|
139
|
+
end
|
140
|
+
|
141
|
+
# backwards compatibility
|
142
|
+
class RestClient::Request
|
143
|
+
Redirect = RestClient::Redirect
|
144
|
+
Unauthorized = RestClient::Unauthorized
|
145
|
+
RequestFailed = RestClient::RequestFailed
|
146
|
+
end
|
File without changes
|
@@ -54,14 +54,17 @@ module RestClient
|
|
54
54
|
# Flatten parameters by converting hashes of hashes to flat hashes
|
55
55
|
# {keys1 => {keys2 => value}} will be transformed into {keys1[key2] => value}
|
56
56
|
def flatten_params(params, parent_key = nil)
|
57
|
-
result =
|
58
|
-
params.
|
57
|
+
result = []
|
58
|
+
params.each do |key, value|
|
59
59
|
calculated_key = parent_key ? "#{parent_key}[#{escape key}]" : escape(key)
|
60
|
-
value = params[key]
|
61
60
|
if value.is_a? Hash
|
62
|
-
result
|
61
|
+
result += flatten_params(value, calculated_key)
|
62
|
+
elsif value.is_a? Array
|
63
|
+
value.each do |elem|
|
64
|
+
result << ["#{calculated_key}[]", elem]
|
65
|
+
end
|
63
66
|
else
|
64
|
-
result[calculated_key
|
67
|
+
result << [calculated_key, value]
|
65
68
|
end
|
66
69
|
end
|
67
70
|
result
|
@@ -88,15 +91,15 @@ module RestClient
|
|
88
91
|
end
|
89
92
|
|
90
93
|
def short_inspect
|
91
|
-
(size > 100 ? "#{size} byte length" : inspect)
|
94
|
+
(size > 100 ? "#{size} byte(s) length" : inspect)
|
92
95
|
end
|
93
96
|
|
94
97
|
end
|
95
98
|
|
96
99
|
class UrlEncoded < Base
|
97
100
|
def build_stream(params = nil)
|
98
|
-
@stream = StringIO.new(flatten_params(params).
|
99
|
-
"#{
|
101
|
+
@stream = StringIO.new(flatten_params(params).collect do |entry|
|
102
|
+
"#{entry[0]}=#{escape(entry[1])}"
|
100
103
|
end.join("&"))
|
101
104
|
@stream.seek(0)
|
102
105
|
end
|
@@ -116,9 +119,9 @@ module RestClient
|
|
116
119
|
@stream.write(b + EOL)
|
117
120
|
|
118
121
|
if params.is_a? Hash
|
119
|
-
x = flatten_params(params)
|
122
|
+
x = flatten_params(params)
|
120
123
|
else
|
121
|
-
x = params
|
124
|
+
x = params
|
122
125
|
end
|
123
126
|
|
124
127
|
last_index = x.length - 1
|
@@ -138,7 +141,7 @@ module RestClient
|
|
138
141
|
end
|
139
142
|
|
140
143
|
def create_regular_field(s, k, v)
|
141
|
-
s.write("Content-Disposition:
|
144
|
+
s.write("Content-Disposition: form-data; name=\"#{k}\"")
|
142
145
|
s.write(EOL)
|
143
146
|
s.write(EOL)
|
144
147
|
s.write(v)
|
@@ -146,7 +149,7 @@ module RestClient
|
|
146
149
|
|
147
150
|
def create_file_field(s, k, v)
|
148
151
|
begin
|
149
|
-
s.write("Content-Disposition:
|
152
|
+
s.write("Content-Disposition: form-data; name=\"#{k}\"; filename=\"#{v.respond_to?(:original_filename) ? v.original_filename : File.basename(v.path)}\"#{EOL}")
|
150
153
|
s.write("Content-Type: #{v.respond_to?(:content_type) ? v.content_type : mime_for(v.path)}#{EOL}")
|
151
154
|
s.write(EOL)
|
152
155
|
while data = v.read(8124)
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require File.dirname(__FILE__) + '/mixin/response'
|
2
|
-
|
3
1
|
module RestClient
|
4
2
|
# The response from RestClient on a raw request looks like a string, but is
|
5
3
|
# actually one of these. 99% of the time you're making a rest call all you
|
@@ -11,13 +9,12 @@ module RestClient
|
|
11
9
|
# In addition, if you do not use the response as a string, you can access
|
12
10
|
# a Tempfile object at res.file, which contains the path to the raw
|
13
11
|
# downloaded request body.
|
14
|
-
class RawResponse
|
15
|
-
include RestClient::Mixin::Response
|
12
|
+
class RawResponse < AbstractResponse
|
16
13
|
|
17
14
|
attr_reader :file
|
18
15
|
|
19
|
-
def initialize
|
20
|
-
|
16
|
+
def initialize tempfile, net_http_res, args
|
17
|
+
super net_http_res, args
|
21
18
|
@file = tempfile
|
22
19
|
end
|
23
20
|
|
@@ -26,5 +23,9 @@ module RestClient
|
|
26
23
|
@file.read
|
27
24
|
end
|
28
25
|
|
26
|
+
def size
|
27
|
+
File.size file
|
28
|
+
end
|
29
|
+
|
29
30
|
end
|
30
31
|
end
|