wrest 4.0.0-universal-java-18

Sign up to get free protection for your applications and to get access to all the features.
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'