wrest 4.0.0-universal-java-18

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 (66) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG +169 -0
  3. data/LICENCE +7 -0
  4. data/README.md +436 -0
  5. data/bin/wrest +4 -0
  6. data/bin/wrest_shell.rb +23 -0
  7. data/lib/wrest/async_request/event_machine_backend.rb +32 -0
  8. data/lib/wrest/async_request/thread_backend.rb +34 -0
  9. data/lib/wrest/async_request/thread_pool.rb +29 -0
  10. data/lib/wrest/async_request.rb +51 -0
  11. data/lib/wrest/cache_proxy.rb +119 -0
  12. data/lib/wrest/caching/memcached.rb +37 -0
  13. data/lib/wrest/caching/redis.rb +38 -0
  14. data/lib/wrest/caching.rb +57 -0
  15. data/lib/wrest/callback.rb +70 -0
  16. data/lib/wrest/components/container/alias_accessors.rb +70 -0
  17. data/lib/wrest/components/container/typecaster.rb +178 -0
  18. data/lib/wrest/components/container.rb +204 -0
  19. data/lib/wrest/components/mutators/base.rb +65 -0
  20. data/lib/wrest/components/mutators/camel_to_snake_case.rb +26 -0
  21. data/lib/wrest/components/mutators/xml_type_caster.rb +56 -0
  22. data/lib/wrest/components/mutators.rb +42 -0
  23. data/lib/wrest/components/translators/content_types.rb +25 -0
  24. data/lib/wrest/components/translators/json.rb +36 -0
  25. data/lib/wrest/components/translators/txt.rb +35 -0
  26. data/lib/wrest/components/translators/xml/conversions.rb +56 -0
  27. data/lib/wrest/components/translators/xml.rb +77 -0
  28. data/lib/wrest/components/translators.rb +30 -0
  29. data/lib/wrest/components.rb +22 -0
  30. data/lib/wrest/core_ext/hash/conversions.rb +45 -0
  31. data/lib/wrest/core_ext/hash.rb +7 -0
  32. data/lib/wrest/core_ext/string/conversions.rb +38 -0
  33. data/lib/wrest/core_ext/string.rb +7 -0
  34. data/lib/wrest/exceptions.rb +38 -0
  35. data/lib/wrest/hash_with_case_insensitive_access.rb +52 -0
  36. data/lib/wrest/hash_with_indifferent_access.rb +442 -0
  37. data/lib/wrest/http_codes.rb +83 -0
  38. data/lib/wrest/http_shared/headers.rb +345 -0
  39. data/lib/wrest/http_shared/standard_headers.rb +22 -0
  40. data/lib/wrest/http_shared/standard_tokens.rb +21 -0
  41. data/lib/wrest/http_shared.rb +25 -0
  42. data/lib/wrest/multipart.rb +84 -0
  43. data/lib/wrest/native/connection_factory.rb +28 -0
  44. data/lib/wrest/native/delete.rb +27 -0
  45. data/lib/wrest/native/get.rb +83 -0
  46. data/lib/wrest/native/options.rb +27 -0
  47. data/lib/wrest/native/patch.rb +27 -0
  48. data/lib/wrest/native/post.rb +27 -0
  49. data/lib/wrest/native/post_multipart.rb +36 -0
  50. data/lib/wrest/native/put.rb +27 -0
  51. data/lib/wrest/native/put_multipart.rb +36 -0
  52. data/lib/wrest/native/redirection.rb +39 -0
  53. data/lib/wrest/native/request.rb +161 -0
  54. data/lib/wrest/native/response.rb +278 -0
  55. data/lib/wrest/native/session.rb +66 -0
  56. data/lib/wrest/native.rb +36 -0
  57. data/lib/wrest/test/request_patches.rb +12 -0
  58. data/lib/wrest/test.rb +3 -0
  59. data/lib/wrest/uri/builders.rb +48 -0
  60. data/lib/wrest/uri.rb +312 -0
  61. data/lib/wrest/uri_template.rb +63 -0
  62. data/lib/wrest/utils.rb +129 -0
  63. data/lib/wrest/version.rb +14 -0
  64. data/lib/wrest.rb +77 -0
  65. data/lib/wrest_no_ext.rb +7 -0
  66. metadata +286 -0
data/lib/wrest/uri.rb ADDED
@@ -0,0 +1,312 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2009 Sidu Ponnappa
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
9
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and limitations under the License.
11
+
12
+ module Wrest # :nodoc:
13
+ # Wrest::Uri provides a simple api for
14
+ # REST calls. String#to_uri is a convenience
15
+ # method to build a Wrest::Uri from a string url.
16
+ # Note that a Wrest::Uri is immutable.
17
+ #
18
+ # Basic HTTP Authentication is supported.
19
+ # Example:
20
+ # "http://kaiwren:fupuppies@coathangers.com/portal/1".to_uri
21
+ # "http://coathangers.com/portal/1".to_uri(:username => 'kaiwren', :password => 'fupuppies')
22
+ #
23
+ # The second form is preferred as it can handle passwords with special characters like ^ and @
24
+ #
25
+ # You can find examples that use real APIs (like delicious) under the wrest/examples directory.
26
+ class Uri
27
+ attr_reader :uri, :username, :password, :uri_string, :uri_path, :query, :default_headers
28
+
29
+ # Valid tuples for the options are:
30
+ # :asynchronous_backend => Can currently be set to either Wrest::AsyncRequest::EventMachineBackend.new
31
+ # or Wrest::AsyncRequest::ThreadBackend.new. Easier to do using Uri#using_em and
32
+ # Uri#using_threads.
33
+ # :callback => Accepts a hash where the keys are response codes or ranges of response codes and
34
+ # the values are the corresponding blocks that will be invoked should the response
35
+ # code match the key.
36
+ # :default_headers => Accepts a hash containing a set of default request headers with which the headers
37
+ # passed to Uri#get, Uri#post etc. are merged. Incoming headers will override the
38
+ # defaults if there are any clashes. Use this to set cookies or use OAuth2 Authorize
39
+ # headers. When extending or cloning a Uri, passing in a new set of default_headers
40
+ # will result in the old set being overridden.
41
+ # :username, :password => HTTP authentication. Passing nil for either username or password will skip it.
42
+ # See Wrest::Native::Request for other available options and their default values.
43
+ def initialize(uri_string, options = {})
44
+ @options = options.clone
45
+ setup_uri_state!(uri_string)
46
+ setup_request_config!
47
+ end
48
+
49
+ # Builds a Wrest::UriTemplate by extending the current URI
50
+ # with the pattern passed to it.
51
+ def to_template(pattern)
52
+ template_pattern = URI.join(uri_string, pattern).to_s
53
+ UriTemplate.new(template_pattern, @options)
54
+ end
55
+
56
+ # Build a new Wrest::Uri by appending _path_ to
57
+ # the current uri. If the original Wrest::Uri
58
+ # has a username and password, that will be
59
+ # copied to the new Wrest::Uri as well.
60
+ #
61
+ # Example:
62
+ # uri = "https://localhost:3000/v1".to_uri
63
+ # uri['/oogas/1'].get
64
+ #
65
+ # To change the username and password on the new
66
+ # instance, simply pass them as an options map.
67
+ #
68
+ # Example:
69
+ # uri = "https://localhost:3000/v1".to_uri(:username => 'foo', :password => 'bar')
70
+ # uri['/oogas/1', {:username => 'meh', :password => 'baz'}].get
71
+ def [](path, options = nil)
72
+ Uri.new(uri + File.join(uri_path, path), options || @options)
73
+ end
74
+
75
+ # Clones a Uri, building a new instance with exactly the same uri string.
76
+ # You can however change the Uri options or add new ones.
77
+ def clone(opts = {})
78
+ merged_options = @options.merge(opts)
79
+ merged_options[:default_headers] = opts[:default_headers] ? @default_headers.merge(opts[:default_headers]) : {}
80
+ Uri.new(@uri_string, merged_options)
81
+ end
82
+
83
+ def eql?(other)
84
+ self == other
85
+ end
86
+
87
+ def ==(other)
88
+ return false if other.class != self.class
89
+
90
+ other.uri == uri && username == other.username && password == other.password
91
+ end
92
+
93
+ def hash
94
+ [@uri, @username, @password].hash
95
+ end
96
+
97
+ # This produces exactly the same string as the Wrest::Uri was constructed with.
98
+ # If the orignial URI contained a HTTP username and password, that too will
99
+ # show up, so be careful if using this for logging.
100
+ def to_s
101
+ uri_string
102
+ end
103
+
104
+ # :nodoc:
105
+ def build_get(parameters = {}, headers = {}, &block)
106
+ Http::Get.new(self, parameters, default_headers.merge(headers),
107
+ block ? @options.merge(callback_block: block) : @options)
108
+ end
109
+
110
+ # :nodoc:
111
+ def build_put(body = '', headers = {}, parameters = {}, &block)
112
+ Http::Put.new(self, body.to_s, default_headers.merge(headers), parameters,
113
+ block ? @options.merge(callback_block: block) : @options)
114
+ end
115
+
116
+ # :nodoc:
117
+ def build_patch(body = '', headers = {}, parameters = {}, &block)
118
+ Http::Patch.new(self, body.to_s, default_headers.merge(headers), parameters,
119
+ block ? @options.merge(callback_block: block) : @options)
120
+ end
121
+
122
+ # :nodoc:
123
+ def build_post(body = '', headers = {}, parameters = {}, &block)
124
+ Http::Post.new(self, body.to_s, default_headers.merge(headers), parameters,
125
+ block ? @options.merge(callback_block: block) : @options)
126
+ end
127
+
128
+ # :nodoc:
129
+ def build_post_form(parameters = {}, headers = {}, &block)
130
+ headers = default_headers.merge(headers).merge(Wrest::H::ContentType => Wrest::T::FormEncoded)
131
+ body = Utils.hash_to_param(parameters)
132
+ Http::Post.new(self, body, headers, {}, block ? @options.merge(callback_block: block) : @options)
133
+ end
134
+
135
+ # :nodoc:
136
+ def build_delete(parameters = {}, headers = {}, &block)
137
+ Http::Delete.new(self, parameters, default_headers.merge(headers),
138
+ block ? @options.merge(callback_block: block) : @options)
139
+ end
140
+
141
+ # Make a GET request to this URI. This is a convenience API
142
+ # that creates a Wrest::Native::Get, executes it and returns a Wrest::Native::Response.
143
+ #
144
+ # Remember to escape all parameter strings if necessary, using URI.escape
145
+ def get(parameters = {}, headers = {}, &block)
146
+ build_get(parameters, headers, &block).invoke
147
+ end
148
+
149
+ # Make a GET request to this URI. This is a convenience API
150
+ # that creates a Wrest::Native::Get.
151
+ #
152
+ # Remember to escape all parameter strings if necessary, using URI.escape
153
+ #
154
+ # Note: get_async does not return a response and the response should be accessed through callbacks.
155
+ # This implementation of asynchronous get is currently in alpha. Hence, it should not be used in production.
156
+ def get_async(parameters = {}, headers = {}, &block)
157
+ @asynchronous_backend.execute(build_get(parameters, headers, &block))
158
+ end
159
+
160
+ # Make a PUT request to this URI. This is a convenience API
161
+ # that creates a Wrest::Native::Put, executes it and returns a Wrest::Native::Response.
162
+ #
163
+ # Remember to escape all parameter strings if necessary, using URI.escape
164
+ def put(body = '', headers = {}, parameters = {}, &block)
165
+ build_put(body, headers, parameters, &block).invoke
166
+ end
167
+
168
+ # Make a PUT request to this URI. This is a convenience API
169
+ # that creates a Wrest::Native::Put.
170
+ #
171
+ # Remember to escape all parameter strings if necessary, using URI.escape
172
+ #
173
+ # Note: put_async does not return a response and the response should be accessed through callbacks.
174
+ # This implementation of asynchronous put is currently in alpha. Hence, it should not be used in production.
175
+ def put_async(body = '', headers = {}, parameters = {}, &block)
176
+ @asynchronous_backend.execute(build_put(body, headers, parameters, &block))
177
+ end
178
+
179
+ # Make a PATCH request to this URI. This is a convenience API
180
+ # that creates a Wrest::Native::Patch, executes it and returns a Wrest::Native::Response.
181
+ #
182
+ # Remember to escape all parameter strings if necessary, using URI.escape
183
+ def patch(body = '', headers = {}, parameters = {}, &block)
184
+ build_patch(body, headers, parameters, &block).invoke
185
+ end
186
+
187
+ # Make a PATCH request to this URI. This is a convenience API
188
+ # that creates a Wrest::Native::Patch.
189
+ #
190
+ # Remember to escape all parameter strings if necessary, using URI.escape
191
+ #
192
+ # Note: patch_async does not return a response and the response should be accessed through callbacks.
193
+ def patch_async(body = '', headers = {}, parameters = {}, &block)
194
+ @asynchronous_backend.execute(build_patch(body, headers, parameters, &block))
195
+ end
196
+
197
+ # Makes a POST request to this URI. This is a convenience API
198
+ # that creates a Wrest::Native::Post, executes it and returns a Wrest::Native::Response.
199
+ #
200
+ # Remember to escape all parameter strings if necessary, using URI.escape
201
+ def post(body = '', headers = {}, parameters = {}, &block)
202
+ build_post(body, headers, parameters, &block).invoke
203
+ end
204
+
205
+ # Makes a POST request to this URI. This is a convenience API
206
+ # that creates a Wrest::Native::Post.
207
+ # Remember to escape all parameter strings if necessary, using URI.escape
208
+ #
209
+ # Note: post_async does not return a response and the response should be accessed through callbacks.
210
+ # This implementation of asynchronous post is currently in alpha. Hence, it should not be used in production.
211
+ def post_async(body = '', headers = {}, parameters = {}, &block)
212
+ @asynchronous_backend.execute(build_post(body, headers, parameters, &block))
213
+ end
214
+
215
+ # Makes a POST request to this URI. This is a convenience API
216
+ # that mimics a form being posted; some allegly RESTful APIs like FCBK require
217
+ # this.
218
+ #
219
+ # Form encoding involves munging the parameters into a string and placing them
220
+ # in the body, as well as setting the Content-Type header to
221
+ # application/x-www-form-urlencoded
222
+ def post_form(parameters = {}, headers = {}, &block)
223
+ build_post_form(parameters, headers, &block).invoke
224
+ end
225
+
226
+ # Makes a POST request to this URI. This is a convenience API
227
+ # that mimics a form being posted; some allegly RESTful APIs like FCBK require
228
+ # this.
229
+ #
230
+ # Form encoding involves munging the parameters into a string and placing them
231
+ # in the body, as well as setting the Content-Type header to
232
+ # application/x-www-form-urlencoded
233
+ #
234
+ # Note: post_form_async does not return a response and the response should be accessed through callbacks.
235
+ # This implementation of asynchronous post_form is currently in alpha. Hence, it should not be used in production.
236
+ def post_form_async(parameters = {}, headers = {}, &block)
237
+ @asynchronous_backend.execute(build_post_form(parameters, headers, &block))
238
+ end
239
+
240
+ # Makes a DELETE request to this URI. This is a convenience API
241
+ # that creates a Wrest::Native::Delete, executes it and returns a Wrest::Native::Response.
242
+ #
243
+ # Remember to escape all parameter strings if necessary, using URI.escape
244
+ def delete(parameters = {}, headers = {}, &block)
245
+ build_delete(parameters, headers, &block).invoke
246
+ end
247
+
248
+ # Makes a DELETE request to this URI. This is a convenience API
249
+ # that creates a Wrest::Native::Delete.
250
+ #
251
+ # Remember to escape all parameter strings if necessary, using URI.escape
252
+ #
253
+ # Note: delete_async does not return a response and the response should be accessed through callbacks.
254
+ # This implementation of asynchronous delete is currently in alpha. Hence, it should not be used in production.
255
+ def delete_async(parameters = {}, headers = {}, &block)
256
+ @asynchronous_backend.execute(build_delete(parameters, headers, &block))
257
+ end
258
+
259
+ # Makes an OPTIONS request to this URI. This is a convenience API
260
+ # that creates a Wrest::Native::Options, executes it and returns the Wrest::Native::Response.
261
+ def options
262
+ Http::Options.new(self, @options).invoke
263
+ end
264
+
265
+ def https?
266
+ @uri.is_a?(URI::HTTPS)
267
+ end
268
+
269
+ # Provides the full path of a request.
270
+ # For example, for
271
+ # http://localhost:3000/demons/1/chi?sort=true
272
+ # this would return
273
+ # /demons/1/chi?sort=true
274
+ def full_path
275
+ uri.request_uri
276
+ end
277
+
278
+ def protocol
279
+ uri.scheme
280
+ end
281
+
282
+ def host
283
+ uri.host
284
+ end
285
+
286
+ def port
287
+ uri.port
288
+ end
289
+
290
+ include Http::ConnectionFactory
291
+ include Uri::Builders
292
+
293
+ private
294
+
295
+ def setup_request_config!
296
+ @username = (@options[:username] ||= @uri.user)
297
+ @password = (@options[:password] ||= @uri.password)
298
+ @asynchronous_backend = @options[:asynchronous_backend] || Wrest::AsyncRequest.default_backend
299
+ @options[:callback] = Callback.new(@options[:callback]) if @options[:callback]
300
+ @default_headers = @options[:default_headers] || {}
301
+ end
302
+
303
+ def setup_uri_state!(uri_string)
304
+ @uri_string = uri_string.to_s
305
+ @uri = URI.parse(@uri_string)
306
+ uri_scheme = URI.split(@uri_string)
307
+ @uri_path = uri_scheme[-4].split('?').first || ''
308
+ @uri_path = (@uri_path.empty? ? '/' : @uri_path)
309
+ @query = uri_scheme[-2] || ''
310
+ end
311
+ end
312
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2009 Sidu Ponnappa
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
9
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and limitations under the License.
11
+
12
+ module Wrest
13
+ class UriTemplate
14
+ attr_reader :uri_pattern
15
+
16
+ def initialize(uri_pattern, options = {})
17
+ @uri_pattern = uri_pattern.clone
18
+ @options = options.clone
19
+ end
20
+
21
+ # Builds a new Wrest::Uri from this uri template
22
+ # by replacing the keys in the options that match with
23
+ # the corressponding values.
24
+ #
25
+ # Example:
26
+ # template = UriTemplate.new("http://coathangers.com/:resource/:id.:format")
27
+ # template.to_uri(:resource => 'shen_coins', :id => 5, :format => :json)
28
+ # => #<Wrest::Uri:0x1225514 @uri=#<URI::HTTP:0x9127d8 URL:http://localhost:3000/shen_coins/5.json>>
29
+ #
30
+ # This feature can also be used to handle HTTP authentication where the username
31
+ # and password needs changing at runtime. However, this approach _will_ fail if
32
+ # the password contains characters like ^ and @.
33
+ #
34
+ # Note that beacuse because both HTTP Auth and UriTemplate
35
+ # use ':' as a delimiter, the pattern does look slightly weird, but it still works.
36
+ # Example:
37
+ # template = UriTemplate.new("http://:username::password@coathangers.com/:resource/:id.:format")
38
+ # template.to_uri(
39
+ # :user => 'kaiwren',
40
+ # :password => 'fupuppies',
41
+ # :resource => 'portal',
42
+ # :id => '1'
43
+ # )
44
+ # => #<Wrest::Uri:0x18e0bec @uri=#<URI::HTTP:0x18e09a8 URL:http://kaiwren:fupuppies@coathangers.com/portal/1>>
45
+ def to_uri(options = {})
46
+ merged_options = @options.merge(options)
47
+ Wrest::Uri.new(merged_options.inject(uri_pattern.clone) do |uri_string, tuple|
48
+ key, value = tuple
49
+ uri_string.gsub(":#{key}", value.to_s)
50
+ end, @options)
51
+ end
52
+
53
+ def [](path)
54
+ UriTemplate.new(File.join(uri_pattern, path))
55
+ end
56
+
57
+ def ==(other)
58
+ return false if other.class != self.class
59
+
60
+ other.uri_pattern == uri_pattern
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Wrest
4
+ module Utils
5
+ module_function
6
+
7
+ # https://github.com/rails/rails/commit/2a371368c91789a4d689d6a84eb20b238c37678a
8
+ # A string is blank if it's empty or contains whitespaces only:
9
+ #
10
+ # "".blank? # => true
11
+ # " ".blank? # => true
12
+ # " ".blank? # => true
13
+ # " something here ".blank? # => false
14
+ #
15
+ def string_blank?(string)
16
+ string !~ /[^[:space:]]/
17
+ end
18
+
19
+ # https://github.com/rails/rails/commit/69b550fc88f0e155ab997476e576142a2dbec324
20
+ # Tries to find a constant with the name specified in the argument string.
21
+ #
22
+ # constantize('Module') # => Module
23
+ # constantize('Foo::Bar') # => Foo::Bar
24
+ #
25
+ # The name is assumed to be the one of a top-level constant, no matter
26
+ # whether it starts with "::" or not. No lexical context is taken into
27
+ # account:
28
+ #
29
+ # C = 'outside'
30
+ # module M
31
+ # C = 'inside'
32
+ # C # => 'inside'
33
+ # constantize('C') # => 'outside', same as ::C
34
+ # end
35
+ #
36
+ # NameError is raised when the name is not in CamelCase or the constant is
37
+ # unknown.
38
+ def string_constantize(camel_cased_word)
39
+ Object.const_get(camel_cased_word)
40
+ end
41
+
42
+ # https://github.com/rails/rails/commit/69b550fc88f0e155ab997476e576142a2dbec324
43
+ # Removes the module part from the expression in the string.
44
+ #
45
+ # demodulize('ActiveSupport::Inflector::Inflections') # => "Inflections"
46
+ # demodulize('Inflections') # => "Inflections"
47
+ # demodulize('::Inflections') # => "Inflections"
48
+ # demodulize('') # => ""
49
+ #
50
+ def string_demodulize(path)
51
+ path = path.to_s
52
+ if (i = path.rindex('::'))
53
+ path[(i + 2)..]
54
+ else
55
+ path
56
+ end
57
+ end
58
+
59
+ # https://github.com/rails/rails/commit/69b550fc88f0e155ab997476e576142a2dbec324
60
+ # Makes an underscored, lowercase form from the expression in the string.
61
+ #
62
+ # Changes '::' to '/' to convert namespaces to paths.
63
+ #
64
+ # underscore('ActiveModel') # => "active_model"
65
+ # underscore('ActiveModel::Errors') # => "active_model/errors"
66
+ #
67
+ # As a rule of thumb you can think of +underscore+ as the inverse of
68
+ # #camelize, though there are cases where that does not hold:
69
+ #
70
+ # camelize(underscore('SSLError')) # => "SslError"
71
+ def string_underscore(camel_cased_word)
72
+ return camel_cased_word.to_s unless /[A-Z-]|::/.match?(camel_cased_word)
73
+
74
+ word = camel_cased_word.to_s.gsub('::', '/')
75
+ word.gsub!(/([A-Z]+)(?=[A-Z][a-z])|([a-z\d])(?=[A-Z])/) { (Regexp.last_match(1) || Regexp.last_match(2)) << '_' }
76
+ word.tr!('-', '_')
77
+ word.downcase!
78
+ word
79
+ end
80
+
81
+ # https://github.com/rails/rails/commit/a0d7247d1509762283c61182ad82c2eed8d54757
82
+ # Returns a string representation of the receiver suitable for use as a URL
83
+ # query string:
84
+ #
85
+ # {:name => 'David', :nationality => 'Danish'}.to_param
86
+ # # => "name=David&nationality=Danish"
87
+ #
88
+ # The string pairs "key=value" that conform the query string
89
+ # are sorted lexicographically in ascending order.
90
+ #
91
+ def hash_to_param(hash)
92
+ hash.collect do |key, value|
93
+ object_to_query(key, value)
94
+ end.sort * '&'
95
+ end
96
+
97
+ # https://github.com/rails/rails/commit/52b71c01fd3c8a87152f55129a8cb3234190734a
98
+ #
99
+ # Converts an object into a string suitable for use as a URL query string, using the given <tt>key</tt> as the
100
+ # param name.
101
+ def object_to_query(key, object)
102
+ "#{CGI.escape(key.to_s)}=#{CGI.escape(object.to_s)}"
103
+ end
104
+
105
+ # https://github.com/rails/rails/commit/18707ab17fa492eb25ad2e8f9818a320dc20b823
106
+ # An object is blank if it's false, empty, or a whitespace string.
107
+ # For example, +nil+, '', ' ', [], {}, and +false+ are all blank.
108
+ #
109
+ # This simplifies
110
+ #
111
+ # !address || address.empty?
112
+ #
113
+ # to
114
+ #
115
+ # address.blank?
116
+ #
117
+ # @return [true, false]
118
+ def object_blank?(object)
119
+ object.respond_to?(:empty?) ? !!object.empty? : !object
120
+ end
121
+
122
+ # https://github.com/rails/rails/commit/6372d23616b13c62c7a12efa89f958b334dd66ae
123
+ # Converts self to an integer number of seconds since the Unix epoch.
124
+ def datetime_to_i(datetime)
125
+ seconds_per_day = 86_400
126
+ ((datetime - ::DateTime.civil(1970)) * seconds_per_day).to_i
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2009-2011 Sidu Ponnappa
4
+
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
8
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
9
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ # See the License for the specific language governing permissions and limitations under the License.
11
+
12
+ module Wrest
13
+ VERSION = '4.0.0'
14
+ end
data/lib/wrest.rb ADDED
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Copyright 2009 Sidu Ponnappa
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
7
+ # Unless required by applicable law or agreed to in writing, software distributed under the License
8
+ # is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9
+ # See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ require 'net/http'
12
+ require 'net/https'
13
+ require 'forwardable'
14
+ require 'date'
15
+ require 'cgi'
16
+ require 'base64'
17
+ require 'logger'
18
+ require 'benchmark'
19
+ require 'concurrent'
20
+ require 'nokogiri'
21
+ require 'json'
22
+
23
+ module Wrest
24
+ Root = File.dirname(__FILE__)
25
+
26
+ $LOAD_PATH.unshift Root
27
+
28
+ def self.logger=(logger)
29
+ @logger = logger
30
+ end
31
+
32
+ def self.logger
33
+ @logger
34
+ end
35
+
36
+ def self.enable_evented_requests!
37
+ require 'wrest/event_machine_backend'
38
+ end
39
+
40
+ # Switch Wrest to using Net::HTTP.
41
+ def self.use_native!
42
+ old_verbose = $VERBOSE
43
+ $VERBOSE = nil
44
+ Wrest.const_set('Http', Wrest::Native)
45
+ ensure
46
+ $VERBOSE = old_verbose
47
+ end
48
+ end
49
+
50
+ Wrest.logger = Logger.new($stdout)
51
+ Wrest.logger.level = Logger::DEBUG
52
+
53
+ require 'wrest/utils'
54
+ require 'wrest/core_ext/string'
55
+ require 'wrest/hash_with_indifferent_access'
56
+ require 'wrest/hash_with_case_insensitive_access'
57
+
58
+ # Load Wrest Core
59
+ require 'wrest/version'
60
+ require 'wrest/cache_proxy'
61
+ require 'wrest/http_shared'
62
+ require 'wrest/http_codes'
63
+ require 'wrest/callback'
64
+ require 'wrest/native'
65
+
66
+ require 'wrest/async_request/thread_pool'
67
+ require 'wrest/async_request/thread_backend'
68
+ require 'wrest/async_request'
69
+
70
+ require 'wrest/caching'
71
+
72
+ # Load Wrest Wrappers
73
+ require 'wrest/uri/builders'
74
+ require 'wrest/uri'
75
+ require 'wrest/uri_template'
76
+ require 'wrest/exceptions'
77
+ require 'wrest/components'
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Opts out of including Wrest's String Extensions
4
+ module Wrest
5
+ NoStringExtensions = true
6
+ end
7
+ require 'wrest'