rest-client 1.8.0 → 2.1.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 (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
@@ -14,7 +14,7 @@ module RestClient
14
14
  #
15
15
  # With a timeout (seconds):
16
16
  #
17
- # RestClient::Resource.new('http://slow', :timeout => 10)
17
+ # RestClient::Resource.new('http://slow', :read_timeout => 10)
18
18
  #
19
19
  # With an open timeout (seconds):
20
20
  #
@@ -51,7 +51,8 @@ module RestClient
51
51
  Request.execute(options.merge(
52
52
  :method => :get,
53
53
  :url => url,
54
- :headers => headers), &(block || @block))
54
+ :headers => headers,
55
+ :log => log), &(block || @block))
55
56
  end
56
57
 
57
58
  def head(additional_headers={}, &block)
@@ -59,7 +60,8 @@ module RestClient
59
60
  Request.execute(options.merge(
60
61
  :method => :head,
61
62
  :url => url,
62
- :headers => headers), &(block || @block))
63
+ :headers => headers,
64
+ :log => log), &(block || @block))
63
65
  end
64
66
 
65
67
  def post(payload, additional_headers={}, &block)
@@ -68,7 +70,8 @@ module RestClient
68
70
  :method => :post,
69
71
  :url => url,
70
72
  :payload => payload,
71
- :headers => headers), &(block || @block))
73
+ :headers => headers,
74
+ :log => log), &(block || @block))
72
75
  end
73
76
 
74
77
  def put(payload, additional_headers={}, &block)
@@ -77,7 +80,8 @@ module RestClient
77
80
  :method => :put,
78
81
  :url => url,
79
82
  :payload => payload,
80
- :headers => headers), &(block || @block))
83
+ :headers => headers,
84
+ :log => log), &(block || @block))
81
85
  end
82
86
 
83
87
  def patch(payload, additional_headers={}, &block)
@@ -86,7 +90,8 @@ module RestClient
86
90
  :method => :patch,
87
91
  :url => url,
88
92
  :payload => payload,
89
- :headers => headers), &(block || @block))
93
+ :headers => headers,
94
+ :log => log), &(block || @block))
90
95
  end
91
96
 
92
97
  def delete(additional_headers={}, &block)
@@ -94,7 +99,8 @@ module RestClient
94
99
  Request.execute(options.merge(
95
100
  :method => :delete,
96
101
  :url => url,
97
- :headers => headers), &(block || @block))
102
+ :headers => headers,
103
+ :log => log), &(block || @block))
98
104
  end
99
105
 
100
106
  def to_s
@@ -113,14 +119,18 @@ module RestClient
113
119
  options[:headers] || {}
114
120
  end
115
121
 
116
- def timeout
117
- options[:timeout]
122
+ def read_timeout
123
+ options[:read_timeout]
118
124
  end
119
125
 
120
126
  def open_timeout
121
127
  options[:open_timeout]
122
128
  end
123
129
 
130
+ def log
131
+ options[:log] || RestClient.log
132
+ end
133
+
124
134
  # Construct a subresource, preserving authentication.
125
135
  #
126
136
  # Example:
@@ -2,20 +2,89 @@ module RestClient
2
2
 
3
3
  # A Response from RestClient, you can access the response body, the code or the headers.
4
4
  #
5
- module Response
5
+ class Response < String
6
6
 
7
7
  include AbstractResponse
8
8
 
9
+ # Return the HTTP response body.
10
+ #
11
+ # Future versions of RestClient will deprecate treating response objects
12
+ # directly as strings, so it will be necessary to call `.body`.
13
+ #
14
+ # @return [String]
15
+ #
9
16
  def body
10
- self
17
+ # Benchmarking suggests that "#{self}" is fastest, and that caching the
18
+ # body string in an instance variable doesn't make it enough faster to be
19
+ # worth the extra memory storage.
20
+ String.new(self)
11
21
  end
12
22
 
13
- def self.create body, net_http_res, args, request
14
- result = body || ''
15
- result.extend Response
16
- result.response_set_vars(net_http_res, args, request)
23
+ # Convert the HTTP response body to a pure String object.
24
+ #
25
+ # @return [String]
26
+ def to_s
27
+ body
28
+ end
29
+
30
+ # Convert the HTTP response body to a pure String object.
31
+ #
32
+ # @return [String]
33
+ def to_str
34
+ body
35
+ end
36
+
37
+ def inspect
38
+ "<RestClient::Response #{code.inspect} #{body_truncated(10).inspect}>"
39
+ end
40
+
41
+ # Initialize a Response object. Because RestClient::Response is
42
+ # (unfortunately) a subclass of String for historical reasons,
43
+ # Response.create is the preferred initializer.
44
+ #
45
+ # @param [String, nil] body The response body from the Net::HTTPResponse
46
+ # @param [Net::HTTPResponse] net_http_res
47
+ # @param [RestClient::Request] request
48
+ # @param [Time] start_time
49
+ def self.create(body, net_http_res, request, start_time=nil)
50
+ result = self.new(body || '')
51
+
52
+ result.response_set_vars(net_http_res, request, start_time)
53
+ fix_encoding(result)
54
+
17
55
  result
18
56
  end
19
57
 
58
+ # Set the String encoding according to the 'Content-Type: charset' header,
59
+ # if possible.
60
+ def self.fix_encoding(response)
61
+ charset = RestClient::Utils.get_encoding_from_headers(response.headers)
62
+ encoding = nil
63
+
64
+ begin
65
+ encoding = Encoding.find(charset) if charset
66
+ rescue ArgumentError
67
+ if response.log
68
+ response.log << "No such encoding: #{charset.inspect}"
69
+ end
70
+ end
71
+
72
+ return unless encoding
73
+
74
+ response.force_encoding(encoding)
75
+
76
+ response
77
+ end
78
+
79
+ private
80
+
81
+ def body_truncated(length)
82
+ b = body
83
+ if b.length > length
84
+ b[0..length] + '...'
85
+ else
86
+ b
87
+ end
88
+ end
20
89
  end
21
90
  end
@@ -0,0 +1,274 @@
1
+ require 'http/accept'
2
+
3
+ module RestClient
4
+ # Various utility methods
5
+ module Utils
6
+
7
+ # Return encoding from an HTTP header hash.
8
+ #
9
+ # We use the RFC 7231 specification and do not impose a default encoding on
10
+ # text. This differs from the older RFC 2616 behavior, which specifies
11
+ # using ISO-8859-1 for text/* content types without a charset.
12
+ #
13
+ # Strings will use the default encoding when this method returns nil. This
14
+ # default is likely to be UTF-8 for Ruby >= 2.0
15
+ #
16
+ # @param headers [Hash<Symbol,String>]
17
+ #
18
+ # @return [String, nil] Return the string encoding or nil if no header is
19
+ # found.
20
+ #
21
+ # @example
22
+ # >> get_encoding_from_headers({:content_type => 'text/plain; charset=UTF-8'})
23
+ # => "UTF-8"
24
+ #
25
+ def self.get_encoding_from_headers(headers)
26
+ type_header = headers[:content_type]
27
+ return nil unless type_header
28
+
29
+ # TODO: remove this hack once we drop support for Ruby 2.0
30
+ if RUBY_VERSION.start_with?('2.0')
31
+ _content_type, params = deprecated_cgi_parse_header(type_header)
32
+
33
+ if params.include?('charset')
34
+ return params.fetch('charset').gsub(/(\A["']*)|(["']*\z)/, '')
35
+ end
36
+
37
+ else
38
+
39
+ begin
40
+ _content_type, params = cgi_parse_header(type_header)
41
+ rescue HTTP::Accept::ParseError
42
+ return nil
43
+ else
44
+ params['charset']
45
+ end
46
+ end
47
+ end
48
+
49
+ # Parse a Content-Type like header.
50
+ #
51
+ # Return the main content-type and a hash of params.
52
+ #
53
+ # @param [String] line
54
+ # @return [Array(String, Hash)]
55
+ #
56
+ def self.cgi_parse_header(line)
57
+ types = HTTP::Accept::MediaTypes.parse(line)
58
+
59
+ if types.empty?
60
+ raise HTTP::Accept::ParseError.new("Found no types in header line")
61
+ end
62
+
63
+ [types.first.mime_type, types.first.parameters]
64
+ end
65
+
66
+ # Parse semi-colon separated, potentially quoted header string iteratively.
67
+ #
68
+ # @private
69
+ #
70
+ # @deprecated This method is deprecated and only exists to support Ruby
71
+ # 2.0, which is not supported by HTTP::Accept.
72
+ #
73
+ # @todo remove this method when dropping support for Ruby 2.0
74
+ #
75
+ def self._cgi_parseparam(s)
76
+ return enum_for(__method__, s) unless block_given?
77
+
78
+ while s[0] == ';'
79
+ s = s[1..-1]
80
+ ends = s.index(';')
81
+ while ends && ends > 0 \
82
+ && (s[0...ends].count('"') -
83
+ s[0...ends].scan('\"').count) % 2 != 0
84
+ ends = s.index(';', ends + 1)
85
+ end
86
+ if ends.nil?
87
+ ends = s.length
88
+ end
89
+ f = s[0...ends]
90
+ yield f.strip
91
+ s = s[ends..-1]
92
+ end
93
+ nil
94
+ end
95
+
96
+ # Parse a Content-Type like header.
97
+ #
98
+ # Return the main content-type and a hash of options.
99
+ #
100
+ # This method was ported directly from Python's cgi.parse_header(). It
101
+ # probably doesn't read or perform particularly well in ruby.
102
+ # https://github.com/python/cpython/blob/3.4/Lib/cgi.py#L301-L331
103
+ #
104
+ # @param [String] line
105
+ # @return [Array(String, Hash)]
106
+ #
107
+ # @deprecated This method is deprecated and only exists to support Ruby
108
+ # 2.0, which is not supported by HTTP::Accept.
109
+ #
110
+ # @todo remove this method when dropping support for Ruby 2.0
111
+ #
112
+ def self.deprecated_cgi_parse_header(line)
113
+ parts = _cgi_parseparam(';' + line)
114
+ key = parts.next
115
+ pdict = {}
116
+
117
+ begin
118
+ while (p = parts.next)
119
+ i = p.index('=')
120
+ if i
121
+ name = p[0...i].strip.downcase
122
+ value = p[i+1..-1].strip
123
+ if value.length >= 2 && value[0] == '"' && value[-1] == '"'
124
+ value = value[1...-1]
125
+ value = value.gsub('\\\\', '\\').gsub('\\"', '"')
126
+ end
127
+ pdict[name] = value
128
+ end
129
+ end
130
+ rescue StopIteration
131
+ end
132
+
133
+ [key, pdict]
134
+ end
135
+
136
+ # Serialize a ruby object into HTTP query string parameters.
137
+ #
138
+ # There is no standard for doing this, so we choose our own slightly
139
+ # idiosyncratic format. The output closely matches the format understood by
140
+ # Rails, Rack, and PHP.
141
+ #
142
+ # If you don't want handling of complex objects and only want to handle
143
+ # simple flat hashes, you may want to use `URI.encode_www_form` instead,
144
+ # which implements HTML5-compliant URL encoded form data.
145
+ #
146
+ # @param [Hash,ParamsArray] object The object to serialize
147
+ #
148
+ # @return [String] A string appropriate for use as an HTTP query string
149
+ #
150
+ # @see {flatten_params}
151
+ #
152
+ # @see URI.encode_www_form
153
+ #
154
+ # @see See also Object#to_query in ActiveSupport
155
+ # @see http://php.net/manual/en/function.http-build-query.php
156
+ # http_build_query in PHP
157
+ # @see See also Rack::Utils.build_nested_query in Rack
158
+ #
159
+ # Notable differences from the ActiveSupport implementation:
160
+ #
161
+ # - Empty hash and empty array are treated the same as nil instead of being
162
+ # omitted entirely from the output. Rather than disappearing, they will
163
+ # appear to be nil instead.
164
+ #
165
+ # It's most common to pass a Hash as the object to serialize, but you can
166
+ # also use a ParamsArray if you want to be able to pass the same key with
167
+ # multiple values and not use the rack/rails array convention.
168
+ #
169
+ # @since 2.0.0
170
+ #
171
+ # @example Simple hashes
172
+ # >> encode_query_string({foo: 123, bar: 456})
173
+ # => 'foo=123&bar=456'
174
+ #
175
+ # @example Simple arrays
176
+ # >> encode_query_string({foo: [1,2,3]})
177
+ # => 'foo[]=1&foo[]=2&foo[]=3'
178
+ #
179
+ # @example Nested hashes
180
+ # >> encode_query_string({outer: {foo: 123, bar: 456}})
181
+ # => 'outer[foo]=123&outer[bar]=456'
182
+ #
183
+ # @example Deeply nesting
184
+ # >> encode_query_string({coords: [{x: 1, y: 0}, {x: 2}, {x: 3}]})
185
+ # => 'coords[][x]=1&coords[][y]=0&coords[][x]=2&coords[][x]=3'
186
+ #
187
+ # @example Null and empty values
188
+ # >> encode_query_string({string: '', empty: nil, list: [], hash: {}})
189
+ # => 'string=&empty&list&hash'
190
+ #
191
+ # @example Nested nulls
192
+ # >> encode_query_string({foo: {string: '', empty: nil}})
193
+ # => 'foo[string]=&foo[empty]'
194
+ #
195
+ # @example Multiple fields with the same name using ParamsArray
196
+ # >> encode_query_string(RestClient::ParamsArray.new([[:foo, 1], [:foo, 2], [:foo, 3]]))
197
+ # => 'foo=1&foo=2&foo=3'
198
+ #
199
+ # @example Nested ParamsArray
200
+ # >> encode_query_string({foo: RestClient::ParamsArray.new([[:a, 1], [:a, 2]])})
201
+ # => 'foo[a]=1&foo[a]=2'
202
+ #
203
+ # >> encode_query_string(RestClient::ParamsArray.new([[:foo, {a: 1}], [:foo, {a: 2}]]))
204
+ # => 'foo[a]=1&foo[a]=2'
205
+ #
206
+ def self.encode_query_string(object)
207
+ flatten_params(object, true).map {|k, v| v.nil? ? k : "#{k}=#{v}" }.join('&')
208
+ end
209
+
210
+ # Transform deeply nested param containers into a flat array of [key,
211
+ # value] pairs.
212
+ #
213
+ # @example
214
+ # >> flatten_params({key1: {key2: 123}})
215
+ # => [["key1[key2]", 123]]
216
+ #
217
+ # @example
218
+ # >> flatten_params({key1: {key2: 123, arr: [1,2,3]}})
219
+ # => [["key1[key2]", 123], ["key1[arr][]", 1], ["key1[arr][]", 2], ["key1[arr][]", 3]]
220
+ #
221
+ # @param object [Hash, ParamsArray] The container to flatten
222
+ # @param uri_escape [Boolean] Whether to URI escape keys and values
223
+ # @param parent_key [String] Should not be passed (used for recursion)
224
+ #
225
+ def self.flatten_params(object, uri_escape=false, parent_key=nil)
226
+ unless object.is_a?(Hash) || object.is_a?(ParamsArray) ||
227
+ (parent_key && object.is_a?(Array))
228
+ raise ArgumentError.new('expected Hash or ParamsArray, got: ' + object.inspect)
229
+ end
230
+
231
+ # transform empty collections into nil, where possible
232
+ if object.empty? && parent_key
233
+ return [[parent_key, nil]]
234
+ end
235
+
236
+ # This is essentially .map(), but we need to do += for nested containers
237
+ object.reduce([]) { |result, item|
238
+ if object.is_a?(Array)
239
+ # item is already the value
240
+ k = nil
241
+ v = item
242
+ else
243
+ # item is a key, value pair
244
+ k, v = item
245
+ k = escape(k.to_s) if uri_escape
246
+ end
247
+
248
+ processed_key = parent_key ? "#{parent_key}[#{k}]" : k
249
+
250
+ case v
251
+ when Array, Hash, ParamsArray
252
+ result.concat flatten_params(v, uri_escape, processed_key)
253
+ else
254
+ v = escape(v.to_s) if uri_escape && v
255
+ result << [processed_key, v]
256
+ end
257
+ }
258
+ end
259
+
260
+ # Encode string for safe transport by URI or form encoding. This uses a CGI
261
+ # style escape, which transforms ` ` into `+` and various special
262
+ # characters into percent encoded forms.
263
+ #
264
+ # This calls URI.encode_www_form_component for the implementation. The only
265
+ # difference between this and CGI.escape is that it does not escape `*`.
266
+ # http://stackoverflow.com/questions/25085992/
267
+ #
268
+ # @see URI.encode_www_form_component
269
+ #
270
+ def self.escape(string)
271
+ URI.encode_www_form_component(string)
272
+ end
273
+ end
274
+ end
@@ -1,5 +1,6 @@
1
1
  module RestClient
2
- VERSION = '1.8.0' unless defined?(self::VERSION)
2
+ VERSION_INFO = [2, 1, 0].freeze
3
+ VERSION = VERSION_INFO.map(&:to_s).join('.').freeze
3
4
 
4
5
  def self.version
5
6
  VERSION
data/lib/restclient.rb CHANGED
@@ -2,16 +2,17 @@ require 'net/http'
2
2
  require 'openssl'
3
3
  require 'stringio'
4
4
  require 'uri'
5
- require 'zlib'
6
5
 
7
6
  require File.dirname(__FILE__) + '/restclient/version'
8
7
  require File.dirname(__FILE__) + '/restclient/platform'
9
8
  require File.dirname(__FILE__) + '/restclient/exceptions'
9
+ require File.dirname(__FILE__) + '/restclient/utils'
10
10
  require File.dirname(__FILE__) + '/restclient/request'
11
11
  require File.dirname(__FILE__) + '/restclient/abstract_response'
12
12
  require File.dirname(__FILE__) + '/restclient/response'
13
13
  require File.dirname(__FILE__) + '/restclient/raw_response'
14
14
  require File.dirname(__FILE__) + '/restclient/resource'
15
+ require File.dirname(__FILE__) + '/restclient/params_array'
15
16
  require File.dirname(__FILE__) + '/restclient/payload'
16
17
  require File.dirname(__FILE__) + '/restclient/windows'
17
18
 
@@ -89,8 +90,24 @@ module RestClient
89
90
  Request.execute(:method => :options, :url => url, :headers => headers, &block)
90
91
  end
91
92
 
92
- class << self
93
- attr_accessor :proxy
93
+ # A global proxy URL to use for all requests. This can be overridden on a
94
+ # per-request basis by passing `:proxy` to RestClient::Request.
95
+ def self.proxy
96
+ @proxy ||= nil
97
+ end
98
+
99
+ def self.proxy=(value)
100
+ @proxy = value
101
+ @proxy_set = true
102
+ end
103
+
104
+ # Return whether RestClient.proxy was set explicitly. We use this to
105
+ # differentiate between no value being set and a value explicitly set to nil.
106
+ #
107
+ # @return [Boolean]
108
+ #
109
+ def self.proxy_set?
110
+ @proxy_set ||= false
94
111
  end
95
112
 
96
113
  # Setup the log for RestClient calls.
@@ -150,6 +167,7 @@ module RestClient
150
167
  # Add a Proc to be called before each request in executed.
151
168
  # The proc parameters will be the http request and the request params.
152
169
  def self.add_before_execution_proc &proc
170
+ raise ArgumentError.new('block is required') unless proc
153
171
  @@before_execution_procs << proc
154
172
  end
155
173
 
data/rest-client.gemspec CHANGED
@@ -8,23 +8,25 @@ Gem::Specification.new do |s|
8
8
  s.authors = ['REST Client Team']
9
9
  s.description = 'A simple HTTP and REST client for Ruby, inspired by the Sinatra microframework style of specifying actions: get, put, post, delete.'
10
10
  s.license = 'MIT'
11
- s.email = 'rest.client@librelist.com'
11
+ s.email = 'discuss@rest-client.groups.io'
12
12
  s.executables = ['restclient']
13
- s.extra_rdoc_files = ['README.rdoc', 'history.md']
13
+ s.extra_rdoc_files = ['README.md', 'history.md']
14
14
  s.files = `git ls-files -z`.split("\0")
15
15
  s.test_files = `git ls-files -z spec/`.split("\0")
16
16
  s.homepage = 'https://github.com/rest-client/rest-client'
17
17
  s.summary = 'Simple HTTP and REST client for Ruby, inspired by microframework syntax for specifying actions.'
18
18
 
19
- s.add_development_dependency('webmock', '~> 1.4')
20
- s.add_development_dependency('rspec', '~> 2.4')
21
- s.add_development_dependency('pry')
22
- s.add_development_dependency('pry-doc')
23
- s.add_development_dependency('rdoc', '>= 2.4.2', '< 5.0')
19
+ s.add_development_dependency('webmock', '~> 2.0')
20
+ s.add_development_dependency('rspec', '~> 3.0')
21
+ s.add_development_dependency('pry', '~> 0')
22
+ s.add_development_dependency('pry-doc', '~> 0')
23
+ s.add_development_dependency('rdoc', '>= 2.4.2', '< 6.0')
24
+ s.add_development_dependency('rubocop', '~> 0.49')
24
25
 
26
+ s.add_dependency('http-accept', '>= 1.7.0', '< 2.0')
25
27
  s.add_dependency('http-cookie', '>= 1.0.2', '< 2.0')
26
- s.add_dependency('mime-types', '>= 1.16', '< 3.0')
27
- s.add_dependency('netrc', '~> 0.7')
28
+ s.add_dependency('mime-types', '>= 1.16', '< 4.0')
29
+ s.add_dependency('netrc', '~> 0.8')
28
30
 
29
- s.required_ruby_version = '>= 1.9.2'
31
+ s.required_ruby_version = '>= 2.0.0'
30
32
  end
data/spec/ISS.jpg ADDED
Binary file
data/spec/helpers.rb ADDED
@@ -0,0 +1,54 @@
1
+ require 'uri'
2
+
3
+ module Helpers
4
+
5
+ # @param [Hash] opts A hash of methods, passed directly to the double
6
+ # definition. Use this to stub other required methods.
7
+ #
8
+ # @return double for Net::HTTPResponse
9
+ def res_double(opts={})
10
+ instance_double('Net::HTTPResponse', {to_hash: {}, body: 'response body'}.merge(opts))
11
+ end
12
+
13
+ # Given a Net::HTTPResponse or double and a Request or double, create a
14
+ # RestClient::Response object.
15
+ #
16
+ # @param net_http_res_double an rspec double for Net::HTTPResponse
17
+ # @param request A RestClient::Request or rspec double
18
+ #
19
+ # @return [RestClient::Response]
20
+ #
21
+ def response_from_res_double(net_http_res_double, request=nil, duration: 1)
22
+ request ||= request_double()
23
+ start_time = Time.now - duration
24
+
25
+ response = RestClient::Response.create(net_http_res_double.body, net_http_res_double, request, start_time)
26
+
27
+ # mock duration to ensure it gets the value we expect
28
+ allow(response).to receive(:duration).and_return(duration)
29
+
30
+ response
31
+ end
32
+
33
+ # Redirect stderr to a string for the duration of the passed block.
34
+ def fake_stderr
35
+ original_stderr = $stderr
36
+ $stderr = StringIO.new
37
+ yield
38
+ $stderr.string
39
+ ensure
40
+ $stderr = original_stderr
41
+ end
42
+
43
+ # Create a double for RestClient::Request
44
+ def request_double(url: 'http://example.com', method: 'get')
45
+ instance_double('RestClient::Request',
46
+ url: url, uri: URI.parse(url), method: method, user: nil, password: nil,
47
+ cookie_jar: HTTP::CookieJar.new, redirection_history: nil,
48
+ args: {url: url, method: method})
49
+ end
50
+
51
+ def test_image_path
52
+ File.dirname(__FILE__) + "/ISS.jpg"
53
+ end
54
+ end
@@ -0,0 +1 @@
1
+ require_relative '../spec_helper'
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
5
+ QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
6
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
7
+ b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
8
+ 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
9
+ CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
10
+ nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
11
+ 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
12
+ T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
13
+ gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
14
+ BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
15
+ TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
16
+ DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
17
+ hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
18
+ 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
19
+ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
20
+ YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
21
+ CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
22
+ -----END CERTIFICATE-----
@@ -0,0 +1,22 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
3
+ MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
4
+ d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
5
+ QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
6
+ MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
7
+ b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
8
+ 9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
9
+ CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
10
+ nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
11
+ 43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
12
+ T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
13
+ gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
14
+ BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
15
+ TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
16
+ DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
17
+ hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
18
+ 06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
19
+ PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
20
+ YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
21
+ CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
22
+ -----END CERTIFICATE-----