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
@@ -0,0 +1,204 @@
|
|
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
|
+
module Components
|
14
|
+
module Container
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'wrest/components/container/typecaster'
|
20
|
+
require 'wrest/components/container/alias_accessors'
|
21
|
+
|
22
|
+
module Wrest
|
23
|
+
module Components
|
24
|
+
# Adds behaviour allowing a class to
|
25
|
+
# contain attributes and providing support
|
26
|
+
# for dynamic getters, setters and query methods.
|
27
|
+
# These methods are added at runtime, on the first
|
28
|
+
# invocation and on a per instance basis.
|
29
|
+
# <tt>respond_to?</tt> however will respond as though
|
30
|
+
# they are all already present.
|
31
|
+
# This means that two different instances of the same
|
32
|
+
# Container could well have different attribute
|
33
|
+
# getters/setters/query methods.
|
34
|
+
#
|
35
|
+
# Note that the first call to a particular getter/setter/query
|
36
|
+
# method will be slower because the method is defined
|
37
|
+
# at that point; subsequent calls will be much faster.
|
38
|
+
#
|
39
|
+
# Also keep in mind that attribute getter/setter/query methods
|
40
|
+
# will _not_ override any existing methods on the class.
|
41
|
+
#
|
42
|
+
# In situations where this is a problem, such as a client consuming Rails
|
43
|
+
# REST services where <tt>id</tt> is a common attribute and clashes with
|
44
|
+
# Object#id, it is recommended to create getter/setter/query methods
|
45
|
+
# on the class (which affects all instances) using the +always_has+ macro.
|
46
|
+
#
|
47
|
+
# If you're implementing your own initialize method
|
48
|
+
# remember to delegate to the default initialize
|
49
|
+
# of Container by invoking <tt>super(attributes)</tt>
|
50
|
+
#
|
51
|
+
# Example:
|
52
|
+
# class ShenCoin
|
53
|
+
# include Wrest::Components::Container
|
54
|
+
# include Wrest::Components::Container::Typecaster
|
55
|
+
#
|
56
|
+
# always_has :id
|
57
|
+
# typecast :id => as_integer
|
58
|
+
# end
|
59
|
+
# coin = ShenCoin.new(:id => '5', :chi_count => 500, :owner => 'Kai Wren')
|
60
|
+
# coin.id # => 5
|
61
|
+
# coin.owner # => 'Kai Wren'
|
62
|
+
module Container
|
63
|
+
def self.included(klass) # :nodoc:
|
64
|
+
klass.extend Container::ClassMethods
|
65
|
+
klass.extend Container::Typecaster::Helpers
|
66
|
+
klass.class_eval do
|
67
|
+
include Container::InstanceMethods
|
68
|
+
include Container::AliasAccessors
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.build_attribute_getter(attribute_name) # :nodoc:
|
73
|
+
"def #{attribute_name};@attributes[:#{attribute_name}];end;"
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.build_attribute_setter(attribute_name) # :nodoc:
|
77
|
+
"def #{attribute_name}=(value);@attributes[:#{attribute_name}] = value;end;"
|
78
|
+
end
|
79
|
+
|
80
|
+
def self.build_attribute_queryer(attribute_name) # :nodoc:
|
81
|
+
"def #{attribute_name}?;not @attributes[:#{attribute_name}].nil?;end;"
|
82
|
+
end
|
83
|
+
|
84
|
+
module ClassMethods
|
85
|
+
# This macro explicitly creates getter, setter and query methods on
|
86
|
+
# an Container, overriding any existing methods with the same names.
|
87
|
+
# This can be used when attribute names clash with existing method names;
|
88
|
+
# an example would be Rails REST resources which frequently make use
|
89
|
+
# an attribute named <tt>id</tt> which clashes with Object#id. Also,
|
90
|
+
# this can be used as a performance optimisation if the incoming
|
91
|
+
# attributes are known beforehand.
|
92
|
+
def always_has(*attribute_names)
|
93
|
+
attribute_names.each do |attribute_name|
|
94
|
+
class_eval(
|
95
|
+
Container.build_attribute_getter(attribute_name) +
|
96
|
+
Container.build_attribute_setter(attribute_name) +
|
97
|
+
Container.build_attribute_queryer(attribute_name)
|
98
|
+
)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
# This is a convenience macro which includes
|
103
|
+
# Wrest::Components::Container::Typecaster into
|
104
|
+
# the class (effectively overwriting this method) before delegating to
|
105
|
+
# the actual typecast method that is a part of that module.
|
106
|
+
# This saves us the effort of explicitly doing the include. Easy to use API is king.
|
107
|
+
#
|
108
|
+
# Remember that using typecast carries a performance penalty.
|
109
|
+
# See Wrest::Components::Container::Typecaster for the actual docs.
|
110
|
+
def typecast(cast_map)
|
111
|
+
class_eval { include Wrest::Components::Container::Typecaster }
|
112
|
+
typecast cast_map
|
113
|
+
end
|
114
|
+
|
115
|
+
# This is the name of the class in snake-case, with any parent
|
116
|
+
# module names removed.
|
117
|
+
#
|
118
|
+
# The class will use as the root element when
|
119
|
+
# serialised to xml after replacing underscores with hyphens.
|
120
|
+
#
|
121
|
+
# This method can be overidden should you need a different name.
|
122
|
+
def element_name
|
123
|
+
@element_name ||= Utils.string_underscore(Utils.string_demodulize(name))
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
module InstanceMethods
|
128
|
+
# Sets up any class to act like
|
129
|
+
# an attributes container by creating
|
130
|
+
# two variables, @attributes and @interface.
|
131
|
+
# Remember not to use these two variable names
|
132
|
+
# when using Container in your own class.
|
133
|
+
def initialize(attributes = {})
|
134
|
+
@attributes = HashWithIndifferentAccess.new(attributes)
|
135
|
+
end
|
136
|
+
|
137
|
+
# A translator is a anything that knows how to serialise a
|
138
|
+
# Hash. It must needs have a method named 'serialise' that
|
139
|
+
# accepts a hash and configuration options, and returns the serialised
|
140
|
+
# result (leaving the hash unchanged, of course).
|
141
|
+
#
|
142
|
+
# Examples for JSON and XML can be found under Wrest::Components::Translators.
|
143
|
+
# These serialised output of these translators will work out of the box for Rails
|
144
|
+
# applications; you may need to roll your own for anything else.
|
145
|
+
#
|
146
|
+
# Note: When serilising to XML, if you want the name of the class as the name of the root node
|
147
|
+
# then you should use the Container#to_xml helper.
|
148
|
+
def serialise_using(translator, options = {})
|
149
|
+
payload = {
|
150
|
+
self.class.element_name => @attributes.dup
|
151
|
+
}
|
152
|
+
translator.serialise(payload, options)
|
153
|
+
end
|
154
|
+
|
155
|
+
def to_xml(options = {})
|
156
|
+
serialise_using(Wrest::Components::Translators::Xml, { root: self.class.element_name }.merge(options))
|
157
|
+
end
|
158
|
+
|
159
|
+
def [](key)
|
160
|
+
@attributes[key.to_sym]
|
161
|
+
end
|
162
|
+
|
163
|
+
def []=(key, value)
|
164
|
+
@attributes[key.to_sym] = value
|
165
|
+
end
|
166
|
+
|
167
|
+
def respond_to_missing?(method_name, *)
|
168
|
+
if super.respond_to?(method_name)
|
169
|
+
true
|
170
|
+
else
|
171
|
+
@attributes.include?(method_name.to_s.gsub(/(\?$)|(=$)/,
|
172
|
+
'').to_sym)
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
# Creates getter, setter and query methods for
|
177
|
+
# attributes on the first call.
|
178
|
+
def method_missing(method_sym, *arguments)
|
179
|
+
method_name = method_sym.to_s
|
180
|
+
attribute_name = method_name.gsub(/(\?$)|(=$)/, '')
|
181
|
+
if @attributes.include?(attribute_name.to_sym) || method_name[-1] == '=' || method_name[-1] == '?'
|
182
|
+
generate_methods!(attribute_name, method_name)
|
183
|
+
send(method_sym, *arguments)
|
184
|
+
else
|
185
|
+
super(method_sym, *arguments)
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
|
191
|
+
def generate_methods!(attribute_name, method_name)
|
192
|
+
case method_name[-1]
|
193
|
+
when '='
|
194
|
+
instance_eval Container.build_attribute_setter(attribute_name)
|
195
|
+
when '?'
|
196
|
+
instance_eval Container.build_attribute_queryer(attribute_name)
|
197
|
+
else
|
198
|
+
instance_eval Container.build_attribute_getter(attribute_name)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,65 @@
|
|
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
|
+
module Components
|
14
|
+
# This is a base implementation of a
|
15
|
+
# hash mutator that ensures that the <tt>mutate</tt> method
|
16
|
+
# will chain to the next mutator by using a
|
17
|
+
# template method.
|
18
|
+
module Mutators
|
19
|
+
class Base
|
20
|
+
attr_reader :next_mutator
|
21
|
+
|
22
|
+
# Registers all subclasses of Mutators::Base in
|
23
|
+
# Mutators::REGISTRY making it easy to reference
|
24
|
+
# and chain them later.
|
25
|
+
#
|
26
|
+
# See Mutators#chain for more information.
|
27
|
+
def self.inherited(subklass)
|
28
|
+
super
|
29
|
+
return if Utils.string_blank?(subklass.name)
|
30
|
+
|
31
|
+
key = Utils.string_underscore(Utils.string_demodulize(subklass.name)).to_sym
|
32
|
+
Wrest::Components::Mutators.registry[key] = subklass
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(next_mutator = nil)
|
36
|
+
@next_mutator = next_mutator
|
37
|
+
end
|
38
|
+
|
39
|
+
# This is a template method which operates on a tuple (well, pair)
|
40
|
+
# from a hash map and guarantees mutator chaining.
|
41
|
+
#
|
42
|
+
# Iterating over any hash using <tt>each</tt> injects
|
43
|
+
# each key/value pair from the hash in the
|
44
|
+
# form of an array.
|
45
|
+
# This method expects of this form as an argument, i.e.
|
46
|
+
# an array with the structure [:key, :value]
|
47
|
+
#
|
48
|
+
# The implementation of the mutation is achieved by
|
49
|
+
# overriding the <tt>do_mutate</tt> method in a subclass.
|
50
|
+
# Note that failing to do so will result in an exception
|
51
|
+
# at runtime.
|
52
|
+
def mutate(tuple)
|
53
|
+
out_tuple = do_mutate(tuple)
|
54
|
+
next_mutator ? next_mutator.mutate(out_tuple) : out_tuple
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
def do_mutate(_tuple)
|
60
|
+
raise Wrest::Exceptions::MethodNotOverridden
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,26 @@
|
|
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
|
+
module Components
|
14
|
+
# Converts the key to snake case
|
15
|
+
#
|
16
|
+
# Example:
|
17
|
+
# Mutators::CamelToSnakeCase.new.mutate(['Spirit-Sword', 'true']) # => ['spirit_sword', 'true']**
|
18
|
+
module Mutators
|
19
|
+
class CamelToSnakeCase < Mutators::Base
|
20
|
+
def do_mutate(tuple)
|
21
|
+
[Utils.string_underscore(tuple.first), tuple.last]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,56 @@
|
|
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
|
+
module Components
|
14
|
+
# This mutator undertands how do type casting
|
15
|
+
# using the type data embedded in a hash
|
16
|
+
# created by deserialising an xml using
|
17
|
+
# ActiveSupport::XmlMini
|
18
|
+
module Mutators
|
19
|
+
class XmlTypeCaster < Mutators::Base
|
20
|
+
def do_mutate(tuple)
|
21
|
+
out_key, in_value = tuple
|
22
|
+
|
23
|
+
out_value = case in_value
|
24
|
+
when Hash
|
25
|
+
process_hash_value(in_value)
|
26
|
+
when Array
|
27
|
+
in_value.collect { |hash| hash.mutate_using(self) }
|
28
|
+
else
|
29
|
+
in_value
|
30
|
+
end
|
31
|
+
|
32
|
+
[out_key, out_value]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def process_hash_value(in_value)
|
38
|
+
if in_value['nil'] == 'true'
|
39
|
+
nil
|
40
|
+
elsif in_value.key?('type')
|
41
|
+
typecast_value(in_value)
|
42
|
+
elsif in_value.key?('__content__')
|
43
|
+
in_value['__content__']
|
44
|
+
else
|
45
|
+
in_value.mutate_using(self)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def typecast_value(in_value)
|
50
|
+
caster = Container::Typecaster::PARSING[in_value['type']]
|
51
|
+
caster ? caster.call(in_value['__content__']) : in_value
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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
|
+
module Components
|
14
|
+
# A mutator understands how to transform
|
15
|
+
# one tuple(key/value pair) from a hash
|
16
|
+
# into another
|
17
|
+
module Mutators
|
18
|
+
# All sublasses of Mutators::Base are automatically
|
19
|
+
# registered here by underscored, symbolised class name.
|
20
|
+
def self.registry
|
21
|
+
@registry ||= {}
|
22
|
+
end
|
23
|
+
|
24
|
+
# Makes referencing and chaining mutators easy.
|
25
|
+
#
|
26
|
+
# Example:
|
27
|
+
# Mutators.chain(:xml_type_caster, :camel_to_snake_case)
|
28
|
+
# is equivalent to
|
29
|
+
# Wrest::Components::Mutators::XmlTypeCaster.new(Wrest::Components::Mutators::CamelToSnakeCase.new)
|
30
|
+
def self.chain(*mutator_keys)
|
31
|
+
mutator_key = mutator_keys.pop
|
32
|
+
mutator_keys.reverse.inject(registry[mutator_key].new) do |next_instance, next_key|
|
33
|
+
registry[next_key].new(next_instance)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
require 'wrest/core_ext/hash'
|
40
|
+
require 'wrest/components/mutators/base'
|
41
|
+
require 'wrest/components/mutators/xml_type_caster'
|
42
|
+
require 'wrest/components/mutators/camel_to_snake_case'
|
@@ -0,0 +1,25 @@
|
|
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
|
+
module Components
|
14
|
+
module Translators
|
15
|
+
# Maps content types to deserialisers
|
16
|
+
CONTENT_TYPES = {
|
17
|
+
'application/xml' => Wrest::Components::Translators::Xml,
|
18
|
+
'text/xml' => Wrest::Components::Translators::Xml,
|
19
|
+
'application/json' => Wrest::Components::Translators::Json,
|
20
|
+
'text/javascript' => Wrest::Components::Translators::Json,
|
21
|
+
'text/plain' => Wrest::Components::Translators::Txt
|
22
|
+
}.freeze
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
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
|
+
module Components
|
14
|
+
module Translators
|
15
|
+
module Json
|
16
|
+
module_function
|
17
|
+
|
18
|
+
def deserialise(response, _options = {})
|
19
|
+
JSON.parse(response.body)
|
20
|
+
end
|
21
|
+
|
22
|
+
def deserialize(response, options = {})
|
23
|
+
deserialise(response, options)
|
24
|
+
end
|
25
|
+
|
26
|
+
def serialise(hash, options = {})
|
27
|
+
hash.to_json(options)
|
28
|
+
end
|
29
|
+
|
30
|
+
def serialize(hash, options = {})
|
31
|
+
serialise(hash, options)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,35 @@
|
|
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
|
+
module Wrest
|
12
|
+
module Components
|
13
|
+
module Translators
|
14
|
+
module Txt
|
15
|
+
module_function
|
16
|
+
|
17
|
+
def deserialise(response, _options = {})
|
18
|
+
response.body
|
19
|
+
end
|
20
|
+
|
21
|
+
def deserialize(response, options = {})
|
22
|
+
deserialise(response, options)
|
23
|
+
end
|
24
|
+
|
25
|
+
def serialise(hash, _options = {})
|
26
|
+
hash.inspect
|
27
|
+
end
|
28
|
+
|
29
|
+
def serialize(hash, options = {})
|
30
|
+
serialise(hash, options)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Wrest
|
4
|
+
module Components
|
5
|
+
module Translators
|
6
|
+
module Xml
|
7
|
+
module Conversions # :nodoc:
|
8
|
+
module Document # :nodoc:
|
9
|
+
def to_hash
|
10
|
+
root.to_hash
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
module Node # :nodoc:
|
15
|
+
CONTENT_ROOT = '__content__'
|
16
|
+
|
17
|
+
# Convert XML document to hash.
|
18
|
+
#
|
19
|
+
# hash::
|
20
|
+
# Hash to merge the converted element into.
|
21
|
+
def to_hash(hash = {})
|
22
|
+
node_hash = {}
|
23
|
+
|
24
|
+
# Insert node hash into parent hash correctly.
|
25
|
+
case hash[name]
|
26
|
+
when Array then hash[name] << node_hash
|
27
|
+
when Hash then hash[name] = [hash[name], node_hash]
|
28
|
+
when nil then hash[name] = node_hash
|
29
|
+
end
|
30
|
+
|
31
|
+
# Handle child elements
|
32
|
+
children.each do |c|
|
33
|
+
if c.element?
|
34
|
+
c.to_hash(node_hash)
|
35
|
+
elsif c.text? || c.cdata?
|
36
|
+
node_hash[CONTENT_ROOT] ||= +''
|
37
|
+
node_hash[CONTENT_ROOT] << c.content
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Remove content node if it is blank and there are child tags
|
42
|
+
node_hash.delete(CONTENT_ROOT) if node_hash.length > 1 && Utils.object_blank?(node_hash[CONTENT_ROOT])
|
43
|
+
|
44
|
+
# Handle attributes
|
45
|
+
attribute_nodes.each { |a| node_hash[a.node_name] = a.value }
|
46
|
+
|
47
|
+
hash
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
Nokogiri::XML::Document.include(Conversions::Document)
|
52
|
+
Nokogiri::XML::Node.include(Conversions::Node)
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,77 @@
|
|
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
|
+
require_relative 'xml/conversions'
|
13
|
+
|
14
|
+
module Wrest
|
15
|
+
module Components
|
16
|
+
module Translators
|
17
|
+
module Xml
|
18
|
+
module_function
|
19
|
+
|
20
|
+
def deserialise(response, options = {})
|
21
|
+
data = response.body
|
22
|
+
data = StringIO.new(data || '') unless data.respond_to?(:read)
|
23
|
+
return {} if data.eof?
|
24
|
+
|
25
|
+
if options[:xpath].nil?
|
26
|
+
parse(data)
|
27
|
+
else
|
28
|
+
search(data, options[:xpath])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def deserialize(response, options = {})
|
33
|
+
deserialise(response, options)
|
34
|
+
end
|
35
|
+
|
36
|
+
def serialise(hash, _options = {})
|
37
|
+
to_xml(hash)
|
38
|
+
end
|
39
|
+
|
40
|
+
def serialize(hash, options = {})
|
41
|
+
serialise(hash, options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def to_xml(hash, builder = nil)
|
45
|
+
builder ||= Nokogiri::XML::Builder.new
|
46
|
+
hash.each_with_object(builder) do |(key, value), inner_builder|
|
47
|
+
if value.is_a?(Hash)
|
48
|
+
inner_builder.send(key.to_s) do |child_builder|
|
49
|
+
to_xml(value, child_builder)
|
50
|
+
end
|
51
|
+
else
|
52
|
+
inner_builder.send(key.to_s, value.to_s)
|
53
|
+
end
|
54
|
+
end.to_xml
|
55
|
+
end
|
56
|
+
|
57
|
+
# Parse an XML Document string or IO into a simple hash using libxml / nokogiri.
|
58
|
+
# data::
|
59
|
+
# XML Document string or IO to parse
|
60
|
+
def parse(data)
|
61
|
+
build_nokogiri_doc(data).to_hash
|
62
|
+
end
|
63
|
+
|
64
|
+
def search(data, xpath)
|
65
|
+
build_nokogiri_doc(data).xpath(xpath)
|
66
|
+
end
|
67
|
+
|
68
|
+
def build_nokogiri_doc(data)
|
69
|
+
doc = Nokogiri::XML(data)
|
70
|
+
raise doc.errors.join("\n") if doc.errors.length.positive?
|
71
|
+
|
72
|
+
doc
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,30 @@
|
|
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
|
+
module Components
|
14
|
+
# Contains strategies/lambdas which know how to deserialise
|
15
|
+
# different content types.
|
16
|
+
module Translators
|
17
|
+
# Loads the appropriate desirialisation strategy based on
|
18
|
+
# the content type
|
19
|
+
def self.lookup(content_type)
|
20
|
+
translator = CONTENT_TYPES[content_type]
|
21
|
+
translator || (raise Wrest::Exceptions::UnsupportedContentType, "Unsupported content type #{content_type}")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'wrest/components/translators/txt'
|
28
|
+
require 'wrest/components/translators/xml'
|
29
|
+
require 'wrest/components/translators/json'
|
30
|
+
require 'wrest/components/translators/content_types'
|
@@ -0,0 +1,22 @@
|
|
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
|
+
# A component is a building block that can
|
14
|
+
# be used while building an object oriented wrapper
|
15
|
+
# around a REST service
|
16
|
+
module Components
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'wrest/components/container'
|
21
|
+
require 'wrest/components/mutators'
|
22
|
+
require 'wrest/components/translators'
|