wrest 4.0.0-universal-java-18
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +169 -0
- data/LICENCE +7 -0
- data/README.md +436 -0
- data/bin/wrest +4 -0
- data/bin/wrest_shell.rb +23 -0
- data/lib/wrest/async_request/event_machine_backend.rb +32 -0
- data/lib/wrest/async_request/thread_backend.rb +34 -0
- data/lib/wrest/async_request/thread_pool.rb +29 -0
- data/lib/wrest/async_request.rb +51 -0
- data/lib/wrest/cache_proxy.rb +119 -0
- data/lib/wrest/caching/memcached.rb +37 -0
- data/lib/wrest/caching/redis.rb +38 -0
- data/lib/wrest/caching.rb +57 -0
- data/lib/wrest/callback.rb +70 -0
- data/lib/wrest/components/container/alias_accessors.rb +70 -0
- data/lib/wrest/components/container/typecaster.rb +178 -0
- data/lib/wrest/components/container.rb +204 -0
- data/lib/wrest/components/mutators/base.rb +65 -0
- data/lib/wrest/components/mutators/camel_to_snake_case.rb +26 -0
- data/lib/wrest/components/mutators/xml_type_caster.rb +56 -0
- data/lib/wrest/components/mutators.rb +42 -0
- data/lib/wrest/components/translators/content_types.rb +25 -0
- data/lib/wrest/components/translators/json.rb +36 -0
- data/lib/wrest/components/translators/txt.rb +35 -0
- data/lib/wrest/components/translators/xml/conversions.rb +56 -0
- data/lib/wrest/components/translators/xml.rb +77 -0
- data/lib/wrest/components/translators.rb +30 -0
- data/lib/wrest/components.rb +22 -0
- data/lib/wrest/core_ext/hash/conversions.rb +45 -0
- data/lib/wrest/core_ext/hash.rb +7 -0
- data/lib/wrest/core_ext/string/conversions.rb +38 -0
- data/lib/wrest/core_ext/string.rb +7 -0
- data/lib/wrest/exceptions.rb +38 -0
- data/lib/wrest/hash_with_case_insensitive_access.rb +52 -0
- data/lib/wrest/hash_with_indifferent_access.rb +442 -0
- data/lib/wrest/http_codes.rb +83 -0
- data/lib/wrest/http_shared/headers.rb +345 -0
- data/lib/wrest/http_shared/standard_headers.rb +22 -0
- data/lib/wrest/http_shared/standard_tokens.rb +21 -0
- data/lib/wrest/http_shared.rb +25 -0
- data/lib/wrest/multipart.rb +84 -0
- data/lib/wrest/native/connection_factory.rb +28 -0
- data/lib/wrest/native/delete.rb +27 -0
- data/lib/wrest/native/get.rb +83 -0
- data/lib/wrest/native/options.rb +27 -0
- data/lib/wrest/native/patch.rb +27 -0
- data/lib/wrest/native/post.rb +27 -0
- data/lib/wrest/native/post_multipart.rb +36 -0
- data/lib/wrest/native/put.rb +27 -0
- data/lib/wrest/native/put_multipart.rb +36 -0
- data/lib/wrest/native/redirection.rb +39 -0
- data/lib/wrest/native/request.rb +161 -0
- data/lib/wrest/native/response.rb +278 -0
- data/lib/wrest/native/session.rb +66 -0
- data/lib/wrest/native.rb +36 -0
- data/lib/wrest/test/request_patches.rb +12 -0
- data/lib/wrest/test.rb +3 -0
- data/lib/wrest/uri/builders.rb +48 -0
- data/lib/wrest/uri.rb +312 -0
- data/lib/wrest/uri_template.rb +63 -0
- data/lib/wrest/utils.rb +129 -0
- data/lib/wrest/version.rb +14 -0
- data/lib/wrest.rb +77 -0
- data/lib/wrest_no_ext.rb +7 -0
- 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
|
data/lib/wrest/utils.rb
ADDED
@@ -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'
|