alinta-rest-client 2.2.0-x64-mingw32

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 (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +9 -0
  3. data/.mailmap +10 -0
  4. data/.rspec +2 -0
  5. data/.rubocop +2 -0
  6. data/.rubocop-disables.yml +393 -0
  7. data/.rubocop.yml +8 -0
  8. data/.travis.yml +49 -0
  9. data/AUTHORS +106 -0
  10. data/Gemfile +11 -0
  11. data/LICENSE +21 -0
  12. data/README.md +896 -0
  13. data/Rakefile +140 -0
  14. data/bin/restclient +92 -0
  15. data/history.md +357 -0
  16. data/lib/rest-client.rb +2 -0
  17. data/lib/rest_client.rb +2 -0
  18. data/lib/restclient.rb +183 -0
  19. data/lib/restclient/abstract_response.rb +252 -0
  20. data/lib/restclient/exceptions.rb +244 -0
  21. data/lib/restclient/params_array.rb +72 -0
  22. data/lib/restclient/payload.rb +234 -0
  23. data/lib/restclient/platform.rb +49 -0
  24. data/lib/restclient/raw_response.rb +49 -0
  25. data/lib/restclient/request.rb +875 -0
  26. data/lib/restclient/resource.rb +178 -0
  27. data/lib/restclient/response.rb +90 -0
  28. data/lib/restclient/utils.rb +274 -0
  29. data/lib/restclient/version.rb +8 -0
  30. data/lib/restclient/windows.rb +8 -0
  31. data/lib/restclient/windows/root_certs.rb +105 -0
  32. data/rest-client.gemspec +32 -0
  33. data/rest-client.windows.gemspec +19 -0
  34. data/spec/ISS.jpg +0 -0
  35. data/spec/helpers.rb +54 -0
  36. data/spec/integration/_lib.rb +1 -0
  37. data/spec/integration/capath_digicert/244b5494.0 +19 -0
  38. data/spec/integration/capath_digicert/81b9768f.0 +19 -0
  39. data/spec/integration/capath_digicert/README +8 -0
  40. data/spec/integration/capath_digicert/digicert.crt +19 -0
  41. data/spec/integration/capath_verisign/415660c1.0 +14 -0
  42. data/spec/integration/capath_verisign/7651b327.0 +14 -0
  43. data/spec/integration/capath_verisign/README +8 -0
  44. data/spec/integration/capath_verisign/verisign.crt +14 -0
  45. data/spec/integration/certs/digicert.crt +19 -0
  46. data/spec/integration/certs/verisign.crt +14 -0
  47. data/spec/integration/httpbin_spec.rb +128 -0
  48. data/spec/integration/integration_spec.rb +118 -0
  49. data/spec/integration/request_spec.rb +127 -0
  50. data/spec/spec_helper.rb +29 -0
  51. data/spec/unit/_lib.rb +1 -0
  52. data/spec/unit/abstract_response_spec.rb +145 -0
  53. data/spec/unit/exceptions_spec.rb +108 -0
  54. data/spec/unit/params_array_spec.rb +36 -0
  55. data/spec/unit/payload_spec.rb +295 -0
  56. data/spec/unit/raw_response_spec.rb +22 -0
  57. data/spec/unit/request2_spec.rb +54 -0
  58. data/spec/unit/request_spec.rb +1238 -0
  59. data/spec/unit/resource_spec.rb +134 -0
  60. data/spec/unit/response_spec.rb +252 -0
  61. data/spec/unit/restclient_spec.rb +80 -0
  62. data/spec/unit/utils_spec.rb +147 -0
  63. data/spec/unit/windows/root_certs_spec.rb +22 -0
  64. metadata +318 -0
@@ -0,0 +1,178 @@
1
+ module RestClient
2
+ # A class that can be instantiated for access to a RESTful resource,
3
+ # including authentication.
4
+ #
5
+ # Example:
6
+ #
7
+ # resource = RestClient::Resource.new('http://some/resource')
8
+ # jpg = resource.get(:accept => 'image/jpg')
9
+ #
10
+ # With HTTP basic authentication:
11
+ #
12
+ # resource = RestClient::Resource.new('http://protected/resource', :user => 'user', :password => 'password')
13
+ # resource.delete
14
+ #
15
+ # With a timeout (seconds):
16
+ #
17
+ # RestClient::Resource.new('http://slow', :read_timeout => 10)
18
+ #
19
+ # With an open timeout (seconds):
20
+ #
21
+ # RestClient::Resource.new('http://behindfirewall', :open_timeout => 10)
22
+ #
23
+ # You can also use resources to share common headers. For headers keys,
24
+ # symbols are converted to strings. Example:
25
+ #
26
+ # resource = RestClient::Resource.new('http://some/resource', :headers => { :client_version => 1 })
27
+ #
28
+ # This header will be transported as X-Client-Version (notice the X prefix,
29
+ # capitalization and hyphens)
30
+ #
31
+ # Use the [] syntax to allocate subresources:
32
+ #
33
+ # site = RestClient::Resource.new('http://example.com', :user => 'adam', :password => 'mypasswd')
34
+ # site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
35
+ #
36
+ class Resource
37
+ attr_reader :url, :options, :block
38
+
39
+ def initialize(url, options={}, backwards_compatibility=nil, &block)
40
+ @url = url
41
+ @block = block
42
+ if options.class == Hash
43
+ @options = options
44
+ else # compatibility with previous versions
45
+ @options = { :user => options, :password => backwards_compatibility }
46
+ end
47
+ end
48
+
49
+ def get(additional_headers={}, &block)
50
+ headers = (options[:headers] || {}).merge(additional_headers)
51
+ Request.execute(options.merge(
52
+ :method => :get,
53
+ :url => url,
54
+ :headers => headers,
55
+ :log => log), &(block || @block))
56
+ end
57
+
58
+ def head(additional_headers={}, &block)
59
+ headers = (options[:headers] || {}).merge(additional_headers)
60
+ Request.execute(options.merge(
61
+ :method => :head,
62
+ :url => url,
63
+ :headers => headers,
64
+ :log => log), &(block || @block))
65
+ end
66
+
67
+ def post(payload, additional_headers={}, &block)
68
+ headers = (options[:headers] || {}).merge(additional_headers)
69
+ Request.execute(options.merge(
70
+ :method => :post,
71
+ :url => url,
72
+ :payload => payload,
73
+ :headers => headers,
74
+ :log => log), &(block || @block))
75
+ end
76
+
77
+ def put(payload, additional_headers={}, &block)
78
+ headers = (options[:headers] || {}).merge(additional_headers)
79
+ Request.execute(options.merge(
80
+ :method => :put,
81
+ :url => url,
82
+ :payload => payload,
83
+ :headers => headers,
84
+ :log => log), &(block || @block))
85
+ end
86
+
87
+ def patch(payload, additional_headers={}, &block)
88
+ headers = (options[:headers] || {}).merge(additional_headers)
89
+ Request.execute(options.merge(
90
+ :method => :patch,
91
+ :url => url,
92
+ :payload => payload,
93
+ :headers => headers,
94
+ :log => log), &(block || @block))
95
+ end
96
+
97
+ def delete(additional_headers={}, &block)
98
+ headers = (options[:headers] || {}).merge(additional_headers)
99
+ Request.execute(options.merge(
100
+ :method => :delete,
101
+ :url => url,
102
+ :headers => headers,
103
+ :log => log), &(block || @block))
104
+ end
105
+
106
+ def to_s
107
+ url
108
+ end
109
+
110
+ def user
111
+ options[:user]
112
+ end
113
+
114
+ def password
115
+ options[:password]
116
+ end
117
+
118
+ def headers
119
+ options[:headers] || {}
120
+ end
121
+
122
+ def read_timeout
123
+ options[:read_timeout]
124
+ end
125
+
126
+ def open_timeout
127
+ options[:open_timeout]
128
+ end
129
+
130
+ def log
131
+ options[:log] || RestClient.log
132
+ end
133
+
134
+ # Construct a subresource, preserving authentication.
135
+ #
136
+ # Example:
137
+ #
138
+ # site = RestClient::Resource.new('http://example.com', 'adam', 'mypasswd')
139
+ # site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
140
+ #
141
+ # This is especially useful if you wish to define your site in one place and
142
+ # call it in multiple locations:
143
+ #
144
+ # def orders
145
+ # RestClient::Resource.new('http://example.com/orders', 'admin', 'mypasswd')
146
+ # end
147
+ #
148
+ # orders.get # GET http://example.com/orders
149
+ # orders['1'].get # GET http://example.com/orders/1
150
+ # orders['1/items'].delete # DELETE http://example.com/orders/1/items
151
+ #
152
+ # Nest resources as far as you want:
153
+ #
154
+ # site = RestClient::Resource.new('http://example.com')
155
+ # posts = site['posts']
156
+ # first_post = posts['1']
157
+ # comments = first_post['comments']
158
+ # comments.post 'Hello', :content_type => 'text/plain'
159
+ #
160
+ def [](suburl, &new_block)
161
+ case
162
+ when block_given? then self.class.new(concat_urls(url, suburl), options, &new_block)
163
+ when block then self.class.new(concat_urls(url, suburl), options, &block)
164
+ else self.class.new(concat_urls(url, suburl), options)
165
+ end
166
+ end
167
+
168
+ def concat_urls(url, suburl) # :nodoc:
169
+ url = url.to_s
170
+ suburl = suburl.to_s
171
+ if url.slice(-1, 1) == '/' or suburl.slice(0, 1) == '/'
172
+ url + suburl
173
+ else
174
+ "#{url}/#{suburl}"
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,90 @@
1
+ module RestClient
2
+
3
+ # A Response from RestClient, you can access the response body, the code or the headers.
4
+ #
5
+ class Response < String
6
+
7
+ include AbstractResponse
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
+ #
16
+ def body
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)
21
+ end
22
+
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
+
55
+ result
56
+ end
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
89
+ end
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