jmeeks-actionwebservice 2.3.2

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 (79) hide show
  1. data/CHANGELOG +320 -0
  2. data/MIT-LICENSE +21 -0
  3. data/README +381 -0
  4. data/Rakefile +173 -0
  5. data/TODO +32 -0
  6. data/examples/googlesearch/README +143 -0
  7. data/examples/googlesearch/autoloading/google_search_api.rb +50 -0
  8. data/examples/googlesearch/autoloading/google_search_controller.rb +57 -0
  9. data/examples/googlesearch/delegated/google_search_service.rb +108 -0
  10. data/examples/googlesearch/delegated/search_controller.rb +7 -0
  11. data/examples/googlesearch/direct/google_search_api.rb +50 -0
  12. data/examples/googlesearch/direct/search_controller.rb +58 -0
  13. data/examples/metaWeblog/README +17 -0
  14. data/examples/metaWeblog/apis/blogger_api.rb +60 -0
  15. data/examples/metaWeblog/apis/blogger_service.rb +34 -0
  16. data/examples/metaWeblog/apis/meta_weblog_api.rb +67 -0
  17. data/examples/metaWeblog/apis/meta_weblog_service.rb +48 -0
  18. data/examples/metaWeblog/controllers/xmlrpc_controller.rb +16 -0
  19. data/generators/web_service/USAGE +28 -0
  20. data/generators/web_service/templates/api_definition.rb +5 -0
  21. data/generators/web_service/templates/controller.rb +8 -0
  22. data/generators/web_service/templates/functional_test.rb +19 -0
  23. data/generators/web_service/web_service_generator.rb +29 -0
  24. data/lib/action_web_service.rb +66 -0
  25. data/lib/action_web_service/api.rb +297 -0
  26. data/lib/action_web_service/base.rb +38 -0
  27. data/lib/action_web_service/casting.rb +149 -0
  28. data/lib/action_web_service/client.rb +3 -0
  29. data/lib/action_web_service/client/base.rb +28 -0
  30. data/lib/action_web_service/client/soap_client.rb +113 -0
  31. data/lib/action_web_service/client/xmlrpc_client.rb +58 -0
  32. data/lib/action_web_service/container.rb +3 -0
  33. data/lib/action_web_service/container/action_controller_container.rb +93 -0
  34. data/lib/action_web_service/container/delegated_container.rb +86 -0
  35. data/lib/action_web_service/container/direct_container.rb +69 -0
  36. data/lib/action_web_service/dispatcher.rb +2 -0
  37. data/lib/action_web_service/dispatcher/abstract.rb +207 -0
  38. data/lib/action_web_service/dispatcher/action_controller_dispatcher.rb +379 -0
  39. data/lib/action_web_service/invocation.rb +202 -0
  40. data/lib/action_web_service/protocol.rb +4 -0
  41. data/lib/action_web_service/protocol/abstract.rb +112 -0
  42. data/lib/action_web_service/protocol/discovery.rb +37 -0
  43. data/lib/action_web_service/protocol/soap_protocol.rb +176 -0
  44. data/lib/action_web_service/protocol/soap_protocol/marshaler.rb +242 -0
  45. data/lib/action_web_service/protocol/xmlrpc_protocol.rb +122 -0
  46. data/lib/action_web_service/scaffolding.rb +281 -0
  47. data/lib/action_web_service/struct.rb +64 -0
  48. data/lib/action_web_service/support/class_inheritable_options.rb +26 -0
  49. data/lib/action_web_service/support/signature_types.rb +226 -0
  50. data/lib/action_web_service/templates/scaffolds/layout.html.erb +65 -0
  51. data/lib/action_web_service/templates/scaffolds/methods.html.erb +6 -0
  52. data/lib/action_web_service/templates/scaffolds/parameters.html.erb +29 -0
  53. data/lib/action_web_service/templates/scaffolds/result.html.erb +30 -0
  54. data/lib/action_web_service/test_invoke.rb +110 -0
  55. data/lib/action_web_service/version.rb +9 -0
  56. data/lib/actionwebservice.rb +1 -0
  57. data/setup.rb +1379 -0
  58. data/test/abstract_client.rb +183 -0
  59. data/test/abstract_dispatcher.rb +548 -0
  60. data/test/abstract_unit.rb +39 -0
  61. data/test/api_test.rb +102 -0
  62. data/test/apis/auto_load_api.rb +3 -0
  63. data/test/apis/broken_auto_load_api.rb +2 -0
  64. data/test/base_test.rb +42 -0
  65. data/test/casting_test.rb +94 -0
  66. data/test/client_soap_test.rb +155 -0
  67. data/test/client_xmlrpc_test.rb +153 -0
  68. data/test/container_test.rb +73 -0
  69. data/test/dispatcher_action_controller_soap_test.rb +138 -0
  70. data/test/dispatcher_action_controller_xmlrpc_test.rb +59 -0
  71. data/test/fixtures/db_definitions/mysql.sql +8 -0
  72. data/test/fixtures/users.yml +12 -0
  73. data/test/gencov +3 -0
  74. data/test/invocation_test.rb +185 -0
  75. data/test/run +6 -0
  76. data/test/scaffolded_controller_test.rb +146 -0
  77. data/test/struct_test.rb +52 -0
  78. data/test/test_invoke_test.rb +112 -0
  79. metadata +175 -0
@@ -0,0 +1,202 @@
1
+ module ActionWebService # :nodoc:
2
+ module Invocation # :nodoc:
3
+ class InvocationError < ActionWebService::ActionWebServiceError # :nodoc:
4
+ end
5
+
6
+ def self.included(base) # :nodoc:
7
+ base.extend(ClassMethods)
8
+ base.send(:include, ActionWebService::Invocation::InstanceMethods)
9
+ end
10
+
11
+ # Invocation interceptors provide a means to execute custom code before
12
+ # and after method invocations on ActionWebService::Base objects.
13
+ #
14
+ # When running in _Direct_ dispatching mode, ActionController filters
15
+ # should be used for this functionality instead.
16
+ #
17
+ # The semantics of invocation interceptors are the same as ActionController
18
+ # filters, and accept the same parameters and options.
19
+ #
20
+ # A _before_ interceptor can also cancel execution by returning +false+,
21
+ # or returning a <tt>[false, "cancel reason"]</tt> array if it wishes to supply
22
+ # a reason for canceling the request.
23
+ #
24
+ # === Example
25
+ #
26
+ # class CustomService < ActionWebService::Base
27
+ # before_invocation :intercept_add, :only => [:add]
28
+ #
29
+ # def add(a, b)
30
+ # a + b
31
+ # end
32
+ #
33
+ # private
34
+ # def intercept_add
35
+ # return [false, "permission denied"] # cancel it
36
+ # end
37
+ # end
38
+ #
39
+ # Options:
40
+ # [<tt>:except</tt>] A list of methods for which the interceptor will NOT be called
41
+ # [<tt>:only</tt>] A list of methods for which the interceptor WILL be called
42
+ module ClassMethods
43
+ # Appends the given +interceptors+ to be called
44
+ # _before_ method invocation.
45
+ def append_before_invocation(*interceptors, &block)
46
+ conditions = extract_conditions!(interceptors)
47
+ interceptors << block if block_given?
48
+ add_interception_conditions(interceptors, conditions)
49
+ append_interceptors_to_chain("before", interceptors)
50
+ end
51
+
52
+ # Prepends the given +interceptors+ to be called
53
+ # _before_ method invocation.
54
+ def prepend_before_invocation(*interceptors, &block)
55
+ conditions = extract_conditions!(interceptors)
56
+ interceptors << block if block_given?
57
+ add_interception_conditions(interceptors, conditions)
58
+ prepend_interceptors_to_chain("before", interceptors)
59
+ end
60
+
61
+ alias :before_invocation :append_before_invocation
62
+
63
+ # Appends the given +interceptors+ to be called
64
+ # _after_ method invocation.
65
+ def append_after_invocation(*interceptors, &block)
66
+ conditions = extract_conditions!(interceptors)
67
+ interceptors << block if block_given?
68
+ add_interception_conditions(interceptors, conditions)
69
+ append_interceptors_to_chain("after", interceptors)
70
+ end
71
+
72
+ # Prepends the given +interceptors+ to be called
73
+ # _after_ method invocation.
74
+ def prepend_after_invocation(*interceptors, &block)
75
+ conditions = extract_conditions!(interceptors)
76
+ interceptors << block if block_given?
77
+ add_interception_conditions(interceptors, conditions)
78
+ prepend_interceptors_to_chain("after", interceptors)
79
+ end
80
+
81
+ alias :after_invocation :append_after_invocation
82
+
83
+ def before_invocation_interceptors # :nodoc:
84
+ read_inheritable_attribute("before_invocation_interceptors")
85
+ end
86
+
87
+ def after_invocation_interceptors # :nodoc:
88
+ read_inheritable_attribute("after_invocation_interceptors")
89
+ end
90
+
91
+ def included_intercepted_methods # :nodoc:
92
+ read_inheritable_attribute("included_intercepted_methods") || {}
93
+ end
94
+
95
+ def excluded_intercepted_methods # :nodoc:
96
+ read_inheritable_attribute("excluded_intercepted_methods") || {}
97
+ end
98
+
99
+ private
100
+ def append_interceptors_to_chain(condition, interceptors)
101
+ write_inheritable_array("#{condition}_invocation_interceptors", interceptors)
102
+ end
103
+
104
+ def prepend_interceptors_to_chain(condition, interceptors)
105
+ interceptors = interceptors + read_inheritable_attribute("#{condition}_invocation_interceptors")
106
+ write_inheritable_attribute("#{condition}_invocation_interceptors", interceptors)
107
+ end
108
+
109
+ def extract_conditions!(interceptors)
110
+ return nil unless interceptors.last.is_a? Hash
111
+ interceptors.pop
112
+ end
113
+
114
+ def add_interception_conditions(interceptors, conditions)
115
+ return unless conditions
116
+ included, excluded = conditions[:only], conditions[:except]
117
+ write_inheritable_hash("included_intercepted_methods", condition_hash(interceptors, included)) && return if included
118
+ write_inheritable_hash("excluded_intercepted_methods", condition_hash(interceptors, excluded)) if excluded
119
+ end
120
+
121
+ def condition_hash(interceptors, *methods)
122
+ interceptors.inject({}) {|hash, interceptor| hash.merge(interceptor => methods.flatten.map {|method| method.to_s})}
123
+ end
124
+ end
125
+
126
+ module InstanceMethods # :nodoc:
127
+ def self.included(base)
128
+ base.class_eval do
129
+ alias_method_chain :perform_invocation, :interception
130
+ end
131
+ end
132
+
133
+ def perform_invocation_with_interception(method_name, params, &block)
134
+ return if before_invocation(method_name, params, &block) == false
135
+ return_value = perform_invocation_without_interception(method_name, params)
136
+ after_invocation(method_name, params, return_value)
137
+ return_value
138
+ end
139
+
140
+ def perform_invocation(method_name, params)
141
+ send(method_name, *params)
142
+ end
143
+
144
+ def before_invocation(name, args, &block)
145
+ call_interceptors(self.class.before_invocation_interceptors, [name, args], &block)
146
+ end
147
+
148
+ def after_invocation(name, args, result)
149
+ call_interceptors(self.class.after_invocation_interceptors, [name, args, result])
150
+ end
151
+
152
+ private
153
+
154
+ def call_interceptors(interceptors, interceptor_args, &block)
155
+ if interceptors and not interceptors.empty?
156
+ interceptors.each do |interceptor|
157
+ next if method_exempted?(interceptor, interceptor_args[0].to_s)
158
+ result = case
159
+ when interceptor.is_a?(Symbol)
160
+ self.send(interceptor, *interceptor_args)
161
+ when interceptor_block?(interceptor)
162
+ interceptor.call(self, *interceptor_args)
163
+ when interceptor_class?(interceptor)
164
+ interceptor.intercept(self, *interceptor_args)
165
+ else
166
+ raise(
167
+ InvocationError,
168
+ "Interceptors need to be either a symbol, proc/method, or a class implementing a static intercept method"
169
+ )
170
+ end
171
+ reason = nil
172
+ if result.is_a?(Array)
173
+ reason = result[1] if result[1]
174
+ result = result[0]
175
+ end
176
+ if result == false
177
+ block.call(reason) if block && reason
178
+ return false
179
+ end
180
+ end
181
+ end
182
+ end
183
+
184
+ def interceptor_block?(interceptor)
185
+ interceptor.respond_to?("call") && (interceptor.arity == 3 || interceptor.arity == -1)
186
+ end
187
+
188
+ def interceptor_class?(interceptor)
189
+ interceptor.respond_to?("intercept")
190
+ end
191
+
192
+ def method_exempted?(interceptor, method_name)
193
+ case
194
+ when self.class.included_intercepted_methods[interceptor]
195
+ !self.class.included_intercepted_methods[interceptor].include?(method_name)
196
+ when self.class.excluded_intercepted_methods[interceptor]
197
+ self.class.excluded_intercepted_methods[interceptor].include?(method_name)
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
@@ -0,0 +1,4 @@
1
+ require 'action_web_service/protocol/abstract'
2
+ require 'action_web_service/protocol/discovery'
3
+ require 'action_web_service/protocol/soap_protocol'
4
+ require 'action_web_service/protocol/xmlrpc_protocol'
@@ -0,0 +1,112 @@
1
+ module ActionWebService # :nodoc:
2
+ module Protocol # :nodoc:
3
+ class ProtocolError < ActionWebServiceError # :nodoc:
4
+ end
5
+
6
+ class AbstractProtocol # :nodoc:
7
+ def setup(controller)
8
+ end
9
+
10
+ def decode_action_pack_request(action_pack_request)
11
+ end
12
+
13
+ def encode_action_pack_request(service_name, public_method_name, raw_body, options={})
14
+ klass = options[:request_class] || SimpleActionPackRequest
15
+ request = klass.new({})
16
+ request.request_parameters['action'] = service_name.to_s
17
+ request.env['RAW_POST_DATA'] = raw_body
18
+ request.env['REQUEST_METHOD'] = 'POST'
19
+ request.env['HTTP_CONTENT_TYPE'] = 'text/xml'
20
+ request
21
+ end
22
+
23
+ def decode_request(raw_request, service_name, protocol_options={})
24
+ end
25
+
26
+ def encode_request(method_name, params, param_types)
27
+ end
28
+
29
+ def decode_response(raw_response)
30
+ end
31
+
32
+ def encode_response(method_name, return_value, return_type, protocol_options={})
33
+ end
34
+
35
+ def protocol_client(api, protocol_name, endpoint_uri, options)
36
+ end
37
+
38
+ def register_api(api)
39
+ end
40
+ end
41
+
42
+ class Request # :nodoc:
43
+ attr :protocol
44
+ attr_accessor :method_name
45
+ attr_accessor :method_params
46
+ attr :service_name
47
+ attr_accessor :api
48
+ attr_accessor :api_method
49
+ attr :protocol_options
50
+
51
+ def initialize(protocol, method_name, method_params, service_name, api=nil, api_method=nil, protocol_options=nil)
52
+ @protocol = protocol
53
+ @method_name = method_name
54
+ @method_params = method_params
55
+ @service_name = service_name
56
+ @api = api
57
+ @api_method = api_method
58
+ @protocol_options = protocol_options || {}
59
+ end
60
+ end
61
+
62
+ class Response # :nodoc:
63
+ attr :body
64
+ attr :content_type
65
+ attr :return_value
66
+
67
+ def initialize(body, content_type, return_value)
68
+ @body = body
69
+ @content_type = content_type
70
+ @return_value = return_value
71
+ end
72
+ end
73
+
74
+ class SimpleActionPackRequest < ActionController::Request # :nodoc:
75
+ def initialize(env = {})
76
+ @env = env
77
+ @qparams = {}
78
+ @rparams = {}
79
+ @cookies = {}
80
+ reset_session
81
+ end
82
+
83
+ def query_parameters
84
+ @qparams
85
+ end
86
+
87
+ def request_parameters
88
+ @rparams
89
+ end
90
+
91
+ def env
92
+ @env
93
+ end
94
+
95
+ def host
96
+ ''
97
+ end
98
+
99
+ def cookies
100
+ @cookies
101
+ end
102
+
103
+ def session
104
+ @session
105
+ end
106
+
107
+ def reset_session
108
+ @session = {}
109
+ end
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,37 @@
1
+ module ActionWebService # :nodoc:
2
+ module Protocol # :nodoc:
3
+ module Discovery # :nodoc:
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ base.send(:include, ActionWebService::Protocol::Discovery::InstanceMethods)
7
+ end
8
+
9
+ module ClassMethods # :nodoc:
10
+ def register_protocol(klass)
11
+ write_inheritable_array("web_service_protocols", [klass])
12
+ end
13
+ end
14
+
15
+ module InstanceMethods # :nodoc:
16
+ private
17
+ def discover_web_service_request(action_pack_request)
18
+ (self.class.read_inheritable_attribute("web_service_protocols") || []).each do |protocol|
19
+ protocol = protocol.create(self)
20
+ request = protocol.decode_action_pack_request(action_pack_request)
21
+ return request unless request.nil?
22
+ end
23
+ nil
24
+ end
25
+
26
+ def create_web_service_client(api, protocol_name, endpoint_uri, options)
27
+ (self.class.read_inheritable_attribute("web_service_protocols") || []).each do |protocol|
28
+ protocol = protocol.create(self)
29
+ client = protocol.protocol_client(api, protocol_name, endpoint_uri, options)
30
+ return client unless client.nil?
31
+ end
32
+ nil
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,176 @@
1
+ require 'action_web_service/protocol/soap_protocol/marshaler'
2
+ require 'soap/streamHandler'
3
+ require 'action_web_service/client/soap_client'
4
+
5
+ module ActionWebService # :nodoc:
6
+ module API # :nodoc:
7
+ class Base # :nodoc:
8
+ def self.soap_client(endpoint_uri, options={})
9
+ ActionWebService::Client::Soap.new self, endpoint_uri, options
10
+ end
11
+ end
12
+ end
13
+
14
+ module Protocol # :nodoc:
15
+ module Soap # :nodoc:
16
+ def self.included(base)
17
+ base.register_protocol(SoapProtocol)
18
+ base.class_inheritable_option(:wsdl_service_name)
19
+ base.class_inheritable_option(:wsdl_namespace)
20
+ end
21
+
22
+ class SoapProtocol < AbstractProtocol # :nodoc:
23
+ AWSEncoding = 'UTF-8'
24
+ XSDEncoding = 'UTF8'
25
+
26
+ attr :marshaler
27
+
28
+ def initialize(namespace=nil)
29
+ namespace ||= 'urn:ActionWebService'
30
+ @marshaler = SoapMarshaler.new namespace
31
+ end
32
+
33
+ def self.create(controller)
34
+ SoapProtocol.new(controller.wsdl_namespace)
35
+ end
36
+
37
+ def decode_action_pack_request(action_pack_request)
38
+ return nil unless soap_action = has_valid_soap_action?(action_pack_request)
39
+ service_name = action_pack_request.parameters['action']
40
+ input_encoding = parse_charset(action_pack_request.env['HTTP_CONTENT_TYPE'])
41
+ protocol_options = {
42
+ :soap_action => soap_action,
43
+ :charset => input_encoding
44
+ }
45
+ decode_request(action_pack_request.raw_post, service_name, protocol_options)
46
+ end
47
+
48
+ def encode_action_pack_request(service_name, public_method_name, raw_body, options={})
49
+ request = super
50
+ request.env['HTTP_SOAPACTION'] = '/soap/%s/%s' % [service_name, public_method_name]
51
+ request
52
+ end
53
+
54
+ def decode_request(raw_request, service_name, protocol_options={})
55
+ envelope = SOAP::Processor.unmarshal(raw_request, :charset => protocol_options[:charset])
56
+ unless envelope
57
+ raise ProtocolError, "Failed to parse SOAP request message"
58
+ end
59
+ request = envelope.body.request
60
+ method_name = request.elename.name
61
+ params = request.collect{ |k, v| marshaler.soap_to_ruby(request[k]) }
62
+ Request.new(self, method_name, params, service_name, nil, nil, protocol_options)
63
+ end
64
+
65
+ def encode_request(method_name, params, param_types)
66
+ param_types.each{ |type| marshaler.register_type(type) } if param_types
67
+ qname = XSD::QName.new(marshaler.namespace, method_name)
68
+ param_def = []
69
+ if param_types
70
+ params = param_types.zip(params).map do |type, param|
71
+ param_def << ['in', type.name, marshaler.lookup_type(type).mapping]
72
+ [type.name, marshaler.ruby_to_soap(param)]
73
+ end
74
+ else
75
+ params = []
76
+ end
77
+ request = SOAP::RPC::SOAPMethodRequest.new(qname, param_def)
78
+ request.set_param(params)
79
+ envelope = create_soap_envelope(request)
80
+ SOAP::Processor.marshal(envelope)
81
+ end
82
+
83
+ def decode_response(raw_response)
84
+ envelope = SOAP::Processor.unmarshal(raw_response)
85
+ unless envelope
86
+ raise ProtocolError, "Failed to parse SOAP request message"
87
+ end
88
+ method_name = envelope.body.request.elename.name
89
+ return_value = envelope.body.response
90
+ return_value = marshaler.soap_to_ruby(return_value) unless return_value.nil?
91
+ [method_name, return_value]
92
+ end
93
+
94
+ def encode_response(method_name, return_value, return_type, protocol_options={})
95
+ if return_type
96
+ return_binding = marshaler.register_type(return_type)
97
+ marshaler.annotate_arrays(return_binding, return_value)
98
+ end
99
+ qname = XSD::QName.new(marshaler.namespace, method_name)
100
+ if return_value.nil?
101
+ response = SOAP::RPC::SOAPMethodResponse.new(qname, nil)
102
+ else
103
+ if return_value.is_a?(Exception)
104
+ detail = SOAP::Mapping::SOAPException.new(return_value)
105
+ response = SOAP::SOAPFault.new(
106
+ SOAP::SOAPQName.new('%s:%s' % [SOAP::SOAPNamespaceTag, 'Server']),
107
+ SOAP::SOAPString.new(return_value.to_s),
108
+ SOAP::SOAPString.new(self.class.name),
109
+ marshaler.ruby_to_soap(detail))
110
+ else
111
+ if return_type
112
+ param_def = [['retval', 'return', marshaler.lookup_type(return_type).mapping]]
113
+ response = SOAP::RPC::SOAPMethodResponse.new(qname, param_def)
114
+ response.retval = marshaler.ruby_to_soap(return_value)
115
+ else
116
+ response = SOAP::RPC::SOAPMethodResponse.new(qname, nil)
117
+ end
118
+ end
119
+ end
120
+ envelope = create_soap_envelope(response)
121
+
122
+ # FIXME: This is not thread-safe, but StringFactory_ in SOAP4R only
123
+ # reads target encoding from the XSD::Charset.encoding variable.
124
+ # This is required to ensure $KCODE strings are converted
125
+ # correctly to UTF-8 for any values of $KCODE.
126
+ previous_encoding = XSD::Charset.encoding
127
+ XSD::Charset.encoding = XSDEncoding
128
+ response_body = SOAP::Processor.marshal(envelope, :charset => AWSEncoding)
129
+ XSD::Charset.encoding = previous_encoding
130
+
131
+ Response.new(response_body, "text/xml; charset=#{AWSEncoding}", return_value)
132
+ end
133
+
134
+ def protocol_client(api, protocol_name, endpoint_uri, options={})
135
+ return nil unless protocol_name == :soap
136
+ ActionWebService::Client::Soap.new(api, endpoint_uri, options)
137
+ end
138
+
139
+ def register_api(api)
140
+ api.api_methods.each do |name, method|
141
+ method.expects.each{ |type| marshaler.register_type(type) } if method.expects
142
+ method.returns.each{ |type| marshaler.register_type(type) } if method.returns
143
+ end
144
+ end
145
+
146
+ private
147
+ def has_valid_soap_action?(request)
148
+ return nil unless request.method == :post
149
+ soap_action = request.env['HTTP_SOAPACTION']
150
+ return nil unless soap_action
151
+ soap_action = soap_action.dup
152
+ soap_action.gsub!(/^"/, '')
153
+ soap_action.gsub!(/"$/, '')
154
+ soap_action.strip!
155
+ return nil if soap_action.empty?
156
+ soap_action
157
+ end
158
+
159
+ def create_soap_envelope(body)
160
+ header = SOAP::SOAPHeader.new
161
+ body = SOAP::SOAPBody.new(body)
162
+ SOAP::SOAPEnvelope.new(header, body)
163
+ end
164
+
165
+ def parse_charset(content_type)
166
+ return AWSEncoding if content_type.nil?
167
+ if /^text\/xml(?:\s*;\s*charset=([^"]+|"[^"]+"))$/i =~ content_type
168
+ $1
169
+ else
170
+ AWSEncoding
171
+ end
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end