rest-client 1.8.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +5 -5
  2. data/.gitignore +2 -0
  3. data/.mailmap +10 -0
  4. data/.rspec +2 -1
  5. data/.rubocop +2 -0
  6. data/.rubocop-disables.yml +386 -0
  7. data/.rubocop.yml +8 -0
  8. data/.travis.yml +56 -8
  9. data/AUTHORS +26 -1
  10. data/README.md +901 -0
  11. data/Rakefile +27 -3
  12. data/bin/restclient +3 -5
  13. data/history.md +181 -0
  14. data/lib/restclient/abstract_response.rb +172 -55
  15. data/lib/restclient/exceptions.rb +96 -55
  16. data/lib/restclient/params_array.rb +72 -0
  17. data/lib/restclient/payload.rb +70 -74
  18. data/lib/restclient/platform.rb +19 -0
  19. data/lib/restclient/raw_response.rb +21 -7
  20. data/lib/restclient/request.rb +540 -281
  21. data/lib/restclient/resource.rb +19 -9
  22. data/lib/restclient/response.rb +75 -6
  23. data/lib/restclient/utils.rb +274 -0
  24. data/lib/restclient/version.rb +2 -1
  25. data/lib/restclient.rb +21 -3
  26. data/rest-client.gemspec +12 -10
  27. data/spec/ISS.jpg +0 -0
  28. data/spec/helpers.rb +54 -0
  29. data/spec/integration/_lib.rb +1 -0
  30. data/spec/integration/capath_digicert/3513523f.0 +22 -0
  31. data/spec/integration/capath_digicert/399e7759.0 +22 -0
  32. data/spec/integration/capath_digicert/digicert.crt +20 -17
  33. data/spec/integration/certs/digicert.crt +20 -17
  34. data/spec/integration/httpbin_spec.rb +128 -0
  35. data/spec/integration/integration_spec.rb +97 -14
  36. data/spec/integration/request_spec.rb +25 -2
  37. data/spec/spec_helper.rb +28 -1
  38. data/spec/unit/_lib.rb +1 -0
  39. data/spec/unit/abstract_response_spec.rb +95 -38
  40. data/spec/unit/exceptions_spec.rb +41 -28
  41. data/spec/unit/params_array_spec.rb +36 -0
  42. data/spec/unit/payload_spec.rb +118 -68
  43. data/spec/unit/raw_response_spec.rb +10 -6
  44. data/spec/unit/request2_spec.rb +34 -12
  45. data/spec/unit/request_spec.rb +745 -424
  46. data/spec/unit/resource_spec.rb +31 -27
  47. data/spec/unit/response_spec.rb +134 -57
  48. data/spec/unit/restclient_spec.rb +16 -15
  49. data/spec/unit/utils_spec.rb +147 -0
  50. data/spec/unit/windows/root_certs_spec.rb +3 -3
  51. metadata +79 -29
  52. data/README.rdoc +0 -324
  53. data/spec/integration/capath_digicert/244b5494.0 +0 -19
  54. data/spec/integration/capath_digicert/81b9768f.0 +0 -19
  55. data/spec/unit/master_shake.jpg +0 -0
@@ -1,5 +1,19 @@
1
1
  module RestClient
2
2
 
3
+ # Hash of HTTP status code => message.
4
+ #
5
+ # 1xx: Informational - Request received, continuing process
6
+ # 2xx: Success - The action was successfully received, understood, and
7
+ # accepted
8
+ # 3xx: Redirection - Further action must be taken in order to complete the
9
+ # request
10
+ # 4xx: Client Error - The request contains bad syntax or cannot be fulfilled
11
+ # 5xx: Server Error - The server failed to fulfill an apparently valid
12
+ # request
13
+ #
14
+ # @see
15
+ # http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
16
+ #
3
17
  STATUSES = {100 => 'Continue',
4
18
  101 => 'Switching Protocols',
5
19
  102 => 'Processing', #WebDAV
@@ -12,6 +26,8 @@ module RestClient
12
26
  205 => 'Reset Content',
13
27
  206 => 'Partial Content',
14
28
  207 => 'Multi-Status', #WebDAV
29
+ 208 => 'Already Reported', # RFC5842
30
+ 226 => 'IM Used', # RFC3229
15
31
 
16
32
  300 => 'Multiple Choices',
17
33
  301 => 'Moved Permanently',
@@ -21,12 +37,13 @@ module RestClient
21
37
  305 => 'Use Proxy', # http/1.1
22
38
  306 => 'Switch Proxy', # no longer used
23
39
  307 => 'Temporary Redirect', # http/1.1
40
+ 308 => 'Permanent Redirect', # RFC7538
24
41
 
25
42
  400 => 'Bad Request',
26
43
  401 => 'Unauthorized',
27
44
  402 => 'Payment Required',
28
45
  403 => 'Forbidden',
29
- 404 => 'Resource Not Found',
46
+ 404 => 'Not Found',
30
47
  405 => 'Method Not Allowed',
31
48
  406 => 'Not Acceptable',
32
49
  407 => 'Proxy Authentication Required',
@@ -35,10 +52,10 @@ module RestClient
35
52
  410 => 'Gone',
36
53
  411 => 'Length Required',
37
54
  412 => 'Precondition Failed',
38
- 413 => 'Request Entity Too Large',
39
- 414 => 'Request-URI Too Long',
55
+ 413 => 'Payload Too Large', # RFC7231 (renamed, see below)
56
+ 414 => 'URI Too Long', # RFC7231 (renamed, see below)
40
57
  415 => 'Unsupported Media Type',
41
- 416 => 'Requested Range Not Satisfiable',
58
+ 416 => 'Range Not Satisfiable', # RFC7233 (renamed, see below)
42
59
  417 => 'Expectation Failed',
43
60
  418 => 'I\'m A Teapot', #RFC2324
44
61
  421 => 'Too Many Connections From This IP',
@@ -61,22 +78,27 @@ module RestClient
61
78
  505 => 'HTTP Version Not Supported',
62
79
  506 => 'Variant Also Negotiates',
63
80
  507 => 'Insufficient Storage', #WebDAV
81
+ 508 => 'Loop Detected', # RFC5842
64
82
  509 => 'Bandwidth Limit Exceeded', #Apache
65
83
  510 => 'Not Extended',
66
84
  511 => 'Network Authentication Required', # RFC6585
67
85
  }
68
86
 
69
- # Compatibility : make the Response act like a Net::HTTPResponse when needed
70
- module ResponseForException
71
- def method_missing symbol, *args
72
- if net_http_res.respond_to? symbol
73
- warn "[warning] The response contained in an RestClient::Exception is now a RestClient::Response instead of a Net::HTTPResponse, please update your code"
74
- net_http_res.send symbol, *args
75
- else
76
- super
77
- end
78
- end
79
- end
87
+ STATUSES_COMPATIBILITY = {
88
+ # The RFCs all specify "Not Found", but "Resource Not Found" was used in
89
+ # earlier RestClient releases.
90
+ 404 => ['ResourceNotFound'],
91
+
92
+ # HTTP 413 was renamed to "Payload Too Large" in RFC7231.
93
+ 413 => ['RequestEntityTooLarge'],
94
+
95
+ # HTTP 414 was renamed to "URI Too Long" in RFC7231.
96
+ 414 => ['RequestURITooLong'],
97
+
98
+ # HTTP 416 was renamed to "Range Not Satisfiable" in RFC7233.
99
+ 416 => ['RequestedRangeNotSatisfiable'],
100
+ }
101
+
80
102
 
81
103
  # This is the base RestClient exception class. Rescue it if you want to
82
104
  # catch any exception that your request might raise
@@ -86,15 +108,13 @@ module RestClient
86
108
  # probably an HTML error page) is e.response.
87
109
  class Exception < RuntimeError
88
110
  attr_accessor :response
111
+ attr_accessor :original_exception
89
112
  attr_writer :message
90
113
 
91
114
  def initialize response = nil, initial_response_code = nil
92
115
  @response = response
93
116
  @message = nil
94
117
  @initial_response_code = initial_response_code
95
-
96
- # compatibility: this make the exception behave like a Net::HTTPResponse
97
- response.extend ResponseForException if response
98
118
  end
99
119
 
100
120
  def http_code
@@ -106,32 +126,35 @@ module RestClient
106
126
  end
107
127
  end
108
128
 
109
- def http_body
110
- @response.body if @response
129
+ def http_headers
130
+ @response.headers if @response
111
131
  end
112
132
 
113
- def inspect
114
- "#{message}: #{http_body}"
133
+ def http_body
134
+ @response.body if @response
115
135
  end
116
136
 
117
137
  def to_s
118
- inspect
138
+ message
119
139
  end
120
140
 
121
141
  def message
122
- @message || self.class.name
142
+ @message || default_message
123
143
  end
124
144
 
145
+ def default_message
146
+ self.class.name
147
+ end
125
148
  end
126
149
 
127
150
  # Compatibility
128
- class ExceptionWithResponse < Exception
151
+ class ExceptionWithResponse < RestClient::Exception
129
152
  end
130
153
 
131
154
  # The request failed with an error code not managed by the code
132
155
  class RequestFailed < ExceptionWithResponse
133
156
 
134
- def message
157
+ def default_message
135
158
  "HTTP status code #{http_code}"
136
159
  end
137
160
 
@@ -140,64 +163,82 @@ module RestClient
140
163
  end
141
164
  end
142
165
 
143
- # We will a create an exception for each status code, see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
166
+ # RestClient exception classes. TODO: move all exceptions into this module.
167
+ #
168
+ # We will a create an exception for each status code, see
169
+ # http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
170
+ #
144
171
  module Exceptions
145
172
  # Map http status codes to the corresponding exception class
146
173
  EXCEPTIONS_MAP = {}
147
174
  end
148
175
 
176
+ # Create HTTP status exception classes
149
177
  STATUSES.each_pair do |code, message|
150
-
151
- # Compatibility
152
- superclass = ([304, 401, 404].include? code) ? ExceptionWithResponse : RequestFailed
153
- klass = Class.new(superclass) do
154
- send(:define_method, :message) {"#{http_code ? "#{http_code} " : ''}#{message}"}
178
+ klass = Class.new(RequestFailed) do
179
+ send(:define_method, :default_message) {"#{http_code ? "#{http_code} " : ''}#{message}"}
155
180
  end
156
- klass_constant = const_set message.delete(' \-\''), klass
181
+ klass_constant = const_set(message.delete(' \-\''), klass)
157
182
  Exceptions::EXCEPTIONS_MAP[code] = klass_constant
158
183
  end
159
184
 
160
- # A redirect was encountered; caught by execute to retry with the new url.
161
- class Redirect < Exception
162
-
163
- def message
164
- 'Redirect'
185
+ # Create HTTP status exception classes used for backwards compatibility
186
+ STATUSES_COMPATIBILITY.each_pair do |code, compat_list|
187
+ klass = Exceptions::EXCEPTIONS_MAP.fetch(code)
188
+ compat_list.each do |old_name|
189
+ const_set(old_name, klass)
165
190
  end
191
+ end
166
192
 
167
- attr_accessor :url
193
+ module Exceptions
194
+ # We have to split the Exceptions module like we do here because the
195
+ # EXCEPTIONS_MAP is under Exceptions, but we depend on
196
+ # RestClient::RequestTimeout below.
197
+
198
+ # Base class for request timeouts.
199
+ #
200
+ # NB: Previous releases of rest-client would raise RequestTimeout both for
201
+ # HTTP 408 responses and for actual connection timeouts.
202
+ class Timeout < RestClient::RequestTimeout
203
+ def initialize(message=nil, original_exception=nil)
204
+ super(nil, nil)
205
+ self.message = message if message
206
+ self.original_exception = original_exception if original_exception
207
+ end
208
+ end
168
209
 
169
- def initialize(url)
170
- @url = url
210
+ # Timeout when connecting to a server. Typically wraps Net::OpenTimeout (in
211
+ # ruby 2.0 or greater).
212
+ class OpenTimeout < Timeout
213
+ def default_message
214
+ 'Timed out connecting to server'
215
+ end
171
216
  end
172
- end
173
217
 
174
- class MaxRedirectsReached < Exception
175
- def message
176
- 'Maximum number of redirect reached'
218
+ # Timeout when reading from a server. Typically wraps Net::ReadTimeout (in
219
+ # ruby 2.0 or greater).
220
+ class ReadTimeout < Timeout
221
+ def default_message
222
+ 'Timed out reading data from server'
223
+ end
177
224
  end
178
225
  end
179
226
 
227
+
180
228
  # The server broke the connection prior to the request completing. Usually
181
229
  # this means it crashed, or sometimes that your network connection was
182
230
  # severed before it could complete.
183
- class ServerBrokeConnection < Exception
231
+ class ServerBrokeConnection < RestClient::Exception
184
232
  def initialize(message = 'Server broke connection')
185
233
  super nil, nil
186
234
  self.message = message
187
235
  end
188
236
  end
189
237
 
190
- class SSLCertificateNotVerified < Exception
191
- def initialize(message)
238
+ class SSLCertificateNotVerified < RestClient::Exception
239
+ def initialize(message = 'SSL certificate not verified')
192
240
  super nil, nil
193
241
  self.message = message
194
242
  end
195
243
  end
196
244
  end
197
-
198
- class RestClient::Request
199
- # backwards compatibility
200
- Redirect = RestClient::Redirect
201
- Unauthorized = RestClient::Unauthorized
202
- RequestFailed = RestClient::RequestFailed
203
- end
@@ -0,0 +1,72 @@
1
+ module RestClient
2
+
3
+ # The ParamsArray class is used to represent an ordered list of [key, value]
4
+ # pairs. Use this when you need to include a key multiple times or want
5
+ # explicit control over parameter ordering.
6
+ #
7
+ # Most of the request payload & parameter functions normally accept a Hash of
8
+ # keys => values, which does not allow for duplicated keys.
9
+ #
10
+ # @see RestClient::Utils.encode_query_string
11
+ # @see RestClient::Utils.flatten_params
12
+ #
13
+ class ParamsArray
14
+ include Enumerable
15
+
16
+ # @param array [Array<Array>] An array of parameter key,value pairs. These
17
+ # pairs may be 2 element arrays [key, value] or single element hashes
18
+ # {key => value}. They may also be single element arrays to represent a
19
+ # key with no value.
20
+ #
21
+ # @example
22
+ # >> ParamsArray.new([[:foo, 123], [:foo, 456], [:bar, 789]])
23
+ # This will be encoded as "foo=123&foo=456&bar=789"
24
+ #
25
+ # @example
26
+ # >> ParamsArray.new({foo: 123, bar: 456})
27
+ # This is valid, but there's no reason not to just use the Hash directly
28
+ # instead of a ParamsArray.
29
+ #
30
+ #
31
+ def initialize(array)
32
+ @array = process_input(array)
33
+ end
34
+
35
+ def each(*args, &blk)
36
+ @array.each(*args, &blk)
37
+ end
38
+
39
+ def empty?
40
+ @array.empty?
41
+ end
42
+
43
+ private
44
+
45
+ def process_input(array)
46
+ array.map {|v| process_pair(v) }
47
+ end
48
+
49
+ # A pair may be:
50
+ # - A single element hash, e.g. {foo: 'bar'}
51
+ # - A two element array, e.g. ['foo', 'bar']
52
+ # - A one element array, e.g. ['foo']
53
+ #
54
+ def process_pair(pair)
55
+ case pair
56
+ when Hash
57
+ if pair.length != 1
58
+ raise ArgumentError.new("Bad # of fields for pair: #{pair.inspect}")
59
+ end
60
+ pair.to_a.fetch(0)
61
+ when Array
62
+ if pair.length > 2
63
+ raise ArgumentError.new("Bad # of fields for pair: #{pair.inspect}")
64
+ end
65
+ [pair.fetch(0), pair[1]]
66
+ else
67
+ # recurse, converting any non-array to an array
68
+ process_pair(pair.to_a)
69
+ end
70
+ end
71
+ end
72
+ end
@@ -1,13 +1,23 @@
1
1
  require 'tempfile'
2
+ require 'securerandom'
2
3
  require 'stringio'
3
- require 'mime/types'
4
+
5
+ begin
6
+ # Use mime/types/columnar if available, for reduced memory usage
7
+ require 'mime/types/columnar'
8
+ rescue LoadError
9
+ require 'mime/types'
10
+ end
4
11
 
5
12
  module RestClient
6
13
  module Payload
7
14
  extend self
8
15
 
9
16
  def generate(params)
10
- if params.is_a?(String)
17
+ if params.is_a?(RestClient::Payload::Base)
18
+ # pass through Payload objects unchanged
19
+ params
20
+ elsif params.is_a?(String)
11
21
  Base.new(params)
12
22
  elsif params.is_a?(Hash)
13
23
  if params.delete(:multipart) == true || has_file?(params)
@@ -15,6 +25,12 @@ module RestClient
15
25
  else
16
26
  UrlEncoded.new(params)
17
27
  end
28
+ elsif params.is_a?(ParamsArray)
29
+ if _has_file?(params)
30
+ Multipart.new(params)
31
+ else
32
+ UrlEncoded.new(params)
33
+ end
18
34
  elsif params.respond_to?(:read)
19
35
  Streamed.new(params)
20
36
  else
@@ -23,28 +39,20 @@ module RestClient
23
39
  end
24
40
 
25
41
  def has_file?(params)
26
- params.any? do |_, v|
27
- case v
28
- when Hash
29
- has_file?(v)
30
- when Array
31
- has_file_array?(v)
32
- else
33
- v.respond_to?(:path) && v.respond_to?(:read)
34
- end
42
+ unless params.is_a?(Hash)
43
+ raise ArgumentError.new("Must pass Hash, not #{params.inspect}")
35
44
  end
45
+ _has_file?(params)
36
46
  end
37
47
 
38
- def has_file_array?(params)
39
- params.any? do |v|
40
- case v
41
- when Hash
42
- has_file?(v)
43
- when Array
44
- has_file_array?(v)
45
- else
46
- v.respond_to?(:path) && v.respond_to?(:read)
47
- end
48
+ def _has_file?(obj)
49
+ case obj
50
+ when Hash, ParamsArray
51
+ obj.any? {|_, v| _has_file?(v) }
52
+ when Array
53
+ obj.any? {|v| _has_file?(v) }
54
+ else
55
+ obj.respond_to?(:path) && obj.respond_to?(:read)
48
56
  end
49
57
  end
50
58
 
@@ -58,40 +66,13 @@ module RestClient
58
66
  @stream.seek(0)
59
67
  end
60
68
 
61
- def read(bytes=nil)
62
- @stream.read(bytes)
63
- end
64
-
65
- alias :to_s :read
66
-
67
- # Flatten parameters by converting hashes of hashes to flat hashes
68
- # {keys1 => {keys2 => value}} will be transformed into [keys1[key2], value]
69
- def flatten_params(params, parent_key = nil)
70
- result = []
71
- params.each do |key, value|
72
- calculated_key = parent_key ? "#{parent_key}[#{handle_key(key)}]" : handle_key(key)
73
- if value.is_a? Hash
74
- result += flatten_params(value, calculated_key)
75
- elsif value.is_a? Array
76
- result += flatten_params_array(value, calculated_key)
77
- else
78
- result << [calculated_key, value]
79
- end
80
- end
81
- result
69
+ def read(*args)
70
+ @stream.read(*args)
82
71
  end
83
72
 
84
- def flatten_params_array value, calculated_key
85
- result = []
86
- value.each do |elem|
87
- if elem.is_a? Hash
88
- result += flatten_params(elem, calculated_key)
89
- elsif elem.is_a? Array
90
- result += flatten_params_array(elem, calculated_key)
91
- else
92
- result << ["#{calculated_key}[]", elem]
93
- end
94
- end
73
+ def to_s
74
+ result = read
75
+ @stream.seek(0)
95
76
  result
96
77
  end
97
78
 
@@ -109,14 +90,20 @@ module RestClient
109
90
  @stream.close unless @stream.closed?
110
91
  end
111
92
 
112
- def inspect
113
- result = to_s.inspect
114
- @stream.seek(0)
115
- result
93
+ def closed?
94
+ @stream.closed?
95
+ end
96
+
97
+ def to_s_inspect
98
+ to_s.inspect
116
99
  end
117
100
 
118
101
  def short_inspect
119
- (size > 500 ? "#{size} byte(s) length" : inspect)
102
+ if size && size > 500
103
+ "#{size} byte(s) length"
104
+ else
105
+ to_s_inspect
106
+ end
120
107
  end
121
108
 
122
109
  end
@@ -134,42 +121,36 @@ module RestClient
134
121
  end
135
122
  end
136
123
 
124
+ # TODO (breaks compatibility): ought to use mime_for() to autodetect the
125
+ # Content-Type for stream objects that have a filename.
126
+
137
127
  alias :length :size
138
128
  end
139
129
 
140
130
  class UrlEncoded < Base
141
131
  def build_stream(params = nil)
142
- @stream = StringIO.new(flatten_params(params).collect do |entry|
143
- "#{entry[0]}=#{handle_key(entry[1])}"
144
- end.join("&"))
132
+ @stream = StringIO.new(Utils.encode_query_string(params))
145
133
  @stream.seek(0)
146
134
  end
147
135
 
148
- # for UrlEncoded escape the keys
149
- def handle_key key
150
- Parser.escape(key.to_s, Escape)
151
- end
152
-
153
136
  def headers
154
137
  super.merge({'Content-Type' => 'application/x-www-form-urlencoded'})
155
138
  end
156
-
157
- Parser = URI.const_defined?(:Parser) ? URI::Parser.new : URI
158
- Escape = Regexp.new("[^#{URI::PATTERN::UNRESERVED}]")
159
139
  end
160
140
 
161
141
  class Multipart < Base
162
142
  EOL = "\r\n"
163
143
 
164
144
  def build_stream(params)
165
- b = "--#{boundary}"
145
+ b = '--' + boundary
166
146
 
167
- @stream = Tempfile.new("RESTClient.Stream.#{rand(1000)}")
147
+ @stream = Tempfile.new('rest-client.multipart.')
168
148
  @stream.binmode
169
149
  @stream.write(b + EOL)
170
150
 
171
- if params.is_a? Hash
172
- x = flatten_params(params)
151
+ case params
152
+ when Hash, ParamsArray
153
+ x = Utils.flatten_params(params)
173
154
  else
174
155
  x = params
175
156
  end
@@ -218,10 +199,25 @@ module RestClient
218
199
  end
219
200
 
220
201
  def boundary
221
- @boundary ||= rand(1_000_000).to_s
202
+ return @boundary if defined?(@boundary) && @boundary
203
+
204
+ # Use the same algorithm used by WebKit: generate 16 random
205
+ # alphanumeric characters, replacing `+` `/` with `A` `B` (included in
206
+ # the list twice) to round out the set of 64.
207
+ s = SecureRandom.base64(12)
208
+ s.tr!('+/', 'AB')
209
+
210
+ @boundary = '----RubyFormBoundary' + s
222
211
  end
223
212
 
224
213
  # for Multipart do not escape the keys
214
+ #
215
+ # Ostensibly multipart keys MAY be percent encoded per RFC 7578, but in
216
+ # practice no major browser that I'm aware of uses percent encoding.
217
+ #
218
+ # Further discussion of multipart encoding:
219
+ # https://github.com/rest-client/rest-client/pull/403#issuecomment-156976930
220
+ #
225
221
  def handle_key key
226
222
  key
227
223
  end
@@ -1,3 +1,5 @@
1
+ require 'rbconfig'
2
+
1
3
  module RestClient
2
4
  module Platform
3
5
  # Return true if we are running on a darwin-based Ruby platform. This will
@@ -26,5 +28,22 @@ module RestClient
26
28
  # defined on mri >= 1.9
27
29
  RUBY_ENGINE == 'jruby'
28
30
  end
31
+
32
+ def self.architecture
33
+ "#{RbConfig::CONFIG['host_os']} #{RbConfig::CONFIG['host_cpu']}"
34
+ end
35
+
36
+ def self.ruby_agent_version
37
+ case RUBY_ENGINE
38
+ when 'jruby'
39
+ "jruby/#{JRUBY_VERSION} (#{RUBY_VERSION}p#{RUBY_PATCHLEVEL})"
40
+ else
41
+ "#{RUBY_ENGINE}/#{RUBY_VERSION}p#{RUBY_PATCHLEVEL}"
42
+ end
43
+ end
44
+
45
+ def self.default_user_agent
46
+ "rest-client/#{VERSION} (#{architecture}) #{ruby_agent_version}"
47
+ end
29
48
  end
30
49
  end
@@ -13,22 +13,36 @@ module RestClient
13
13
 
14
14
  include AbstractResponse
15
15
 
16
- attr_reader :file, :request
16
+ attr_reader :file, :request, :start_time, :end_time
17
17
 
18
- def initialize(tempfile, net_http_res, args, request)
19
- @net_http_res = net_http_res
20
- @args = args
18
+ def inspect
19
+ "<RestClient::RawResponse @code=#{code.inspect}, @file=#{file.inspect}, @request=#{request.inspect}>"
20
+ end
21
+
22
+ # @param [Tempfile] tempfile The temporary file containing the body
23
+ # @param [Net::HTTPResponse] net_http_res
24
+ # @param [RestClient::Request] request
25
+ # @param [Time] start_time
26
+ def initialize(tempfile, net_http_res, request, start_time=nil)
21
27
  @file = tempfile
22
- @request = request
28
+
29
+ # reopen the tempfile so we can read it
30
+ @file.open
31
+
32
+ response_set_vars(net_http_res, request, start_time)
23
33
  end
24
34
 
25
35
  def to_s
26
- @file.open
36
+ body
37
+ end
38
+
39
+ def body
40
+ @file.rewind
27
41
  @file.read
28
42
  end
29
43
 
30
44
  def size
31
- File.size file
45
+ file.size
32
46
  end
33
47
 
34
48
  end