wash_out 0.9.2 → 0.11.0
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.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/.travis.yml +35 -4
- data/Appraisals +8 -12
- data/Gemfile +1 -1
- data/README.md +85 -7
- data/Rakefile +15 -5
- data/app/helpers/wash_out_helper.rb +59 -24
- data/app/views/{wash_with_soap → wash_out}/document/error.builder +0 -0
- data/app/views/{wash_with_soap → wash_out}/document/response.builder +7 -0
- data/app/views/{wash_with_soap → wash_out}/document/wsdl.builder +14 -14
- data/app/views/{wash_with_soap → wash_out}/rpc/error.builder +0 -0
- data/app/views/{wash_with_soap → wash_out}/rpc/response.builder +8 -1
- data/app/views/{wash_with_soap → wash_out}/rpc/wsdl.builder +15 -15
- data/gemfiles/rails_3.2.13.gemfile +21 -0
- data/gemfiles/rails_4.0.0.gemfile +20 -0
- data/gemfiles/rails_4.1.0.gemfile +20 -0
- data/gemfiles/rails_4.2.0.gemfile +20 -0
- data/gemfiles/rails_5.0.0.beta2.gemfile +19 -0
- data/gemfiles/rails_5.0.0.gemfile +19 -0
- data/lib/wash_out/dispatcher.rb +96 -39
- data/lib/wash_out/param.rb +14 -2
- data/lib/wash_out/router.rb +52 -22
- data/lib/wash_out/soap.rb +11 -0
- data/lib/wash_out/version.rb +1 -1
- data/lib/wash_out/wsse.rb +3 -3
- data/lib/wash_out.rb +32 -5
- data/spec/dummy/config/environments/test.rb +1 -0
- data/spec/fixtures/nested_refs_to_arrays.xml +19 -0
- data/spec/fixtures/ref_to_one_array.xml +11 -0
- data/spec/fixtures/refs_to_arrays.xml +16 -0
- data/spec/lib/wash_out/dispatcher_spec.rb +124 -17
- data/spec/lib/wash_out/middleware_spec.rb +8 -8
- data/spec/lib/wash_out/param_spec.rb +43 -11
- data/spec/lib/wash_out/router_spec.rb +33 -5
- data/spec/lib/wash_out/type_spec.rb +9 -9
- data/spec/lib/wash_out_spec.rb +361 -103
- data/spec/spec_helper.rb +26 -4
- metadata +18 -9
data/lib/wash_out/dispatcher.rb
CHANGED
@@ -16,9 +16,8 @@ module WashOut
|
|
16
16
|
class ProgrammerError < Exception; end
|
17
17
|
|
18
18
|
def _authenticate_wsse
|
19
|
-
|
20
19
|
begin
|
21
|
-
xml_security = env['wash_out.soap_data'].values_at(:envelope, :Envelope).compact.first
|
20
|
+
xml_security = request.env['wash_out.soap_data'].values_at(:envelope, :Envelope).compact.first
|
22
21
|
xml_security = xml_security.values_at(:header, :Header).compact.first
|
23
22
|
xml_security = xml_security.values_at(:security, :Security).compact.first
|
24
23
|
username_token = xml_security.values_at(:username_token, :UsernameToken).compact.first
|
@@ -32,22 +31,31 @@ module WashOut
|
|
32
31
|
end
|
33
32
|
|
34
33
|
def _map_soap_parameters
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
value = hash[key].delete_if{|k, v| k.to_s[0] == '@'}
|
34
|
+
self.params = _load_params action_spec[:in],
|
35
|
+
_strip_empty_nodes(action_spec[:in], xml_data)
|
36
|
+
end
|
39
37
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
38
|
+
def _map_soap_headers
|
39
|
+
@_soap_headers = xml_header_data
|
40
|
+
end
|
41
|
+
|
42
|
+
def _strip_empty_nodes(params, hash)
|
43
|
+
hash.keys.each do |key|
|
44
|
+
param = params.detect { |a| a.raw_name.to_s == key.to_s }
|
45
|
+
next if !(param && hash[key].is_a?(Hash))
|
46
|
+
|
47
|
+
value = hash[key].delete_if do |k, _|
|
48
|
+
k.to_s[0] == '@' && !param.map.detect { |a| a.raw_name.to_s == k.to_s }
|
46
49
|
end
|
47
50
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
+
if value.length > 0
|
52
|
+
hash[key] = _strip_empty_nodes param.map, value
|
53
|
+
else
|
54
|
+
hash[key] = nil
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
hash
|
51
59
|
end
|
52
60
|
|
53
61
|
# Creates the final parameter hash based on the request spec and xml_data from the request
|
@@ -64,12 +72,11 @@ module WashOut
|
|
64
72
|
|
65
73
|
# This action generates the WSDL for defined SOAP methods.
|
66
74
|
def _generate_wsdl
|
67
|
-
|
68
75
|
@map = self.class.soap_actions
|
69
76
|
@namespace = soap_config.namespace
|
70
|
-
@name = controller_path
|
77
|
+
@name = controller_path
|
71
78
|
|
72
|
-
render :template => "
|
79
|
+
render :template => "wash_out/#{soap_config.wsdl_style}/wsdl", :layout => false,
|
73
80
|
:content_type => 'text/xml'
|
74
81
|
end
|
75
82
|
|
@@ -124,9 +131,19 @@ module WashOut
|
|
124
131
|
return result_spec
|
125
132
|
}
|
126
133
|
|
127
|
-
|
134
|
+
header = options[:header]
|
135
|
+
if header.present?
|
136
|
+
header = { 'value' => header } unless header.is_a? Hash
|
137
|
+
header = HashWithIndifferentAccess.new(header)
|
138
|
+
end
|
139
|
+
|
140
|
+
render :template => "wash_out/#{soap_config.wsdl_style}/response",
|
128
141
|
:layout => false,
|
129
|
-
:locals => {
|
142
|
+
:locals => {
|
143
|
+
:header => header.present? ? inject.call(header, @action_spec[:header_out])
|
144
|
+
: nil,
|
145
|
+
:result => inject.call(result, @action_spec[:out])
|
146
|
+
},
|
130
147
|
:content_type => 'text/xml'
|
131
148
|
end
|
132
149
|
|
@@ -135,6 +152,10 @@ module WashOut
|
|
135
152
|
render_soap_error("Cannot find SOAP action mapping for #{request.env['wash_out.soap_action']}")
|
136
153
|
end
|
137
154
|
|
155
|
+
def _invalid_request
|
156
|
+
render_soap_error("Invalid SOAP request")
|
157
|
+
end
|
158
|
+
|
138
159
|
def _catch_soap_errors
|
139
160
|
yield
|
140
161
|
rescue SOAPError => error
|
@@ -146,56 +167,92 @@ module WashOut
|
|
146
167
|
# Rails do not support sequental rescue_from handling, that is, rescuing an
|
147
168
|
# exception from a rescue_from handler. Hence this function is a public API.
|
148
169
|
def render_soap_error(message, code=nil)
|
149
|
-
render :template => "
|
170
|
+
render :template => "wash_out/#{soap_config.wsdl_style}/error", :status => 500,
|
150
171
|
:layout => false,
|
151
172
|
:locals => { :error_message => message, :error_code => (code || 'Server') },
|
152
173
|
:content_type => 'text/xml'
|
153
174
|
end
|
154
175
|
|
176
|
+
def soap_request
|
177
|
+
OpenStruct.new({
|
178
|
+
params: @_params,
|
179
|
+
headers: @_soap_headers
|
180
|
+
})
|
181
|
+
end
|
182
|
+
|
155
183
|
def self.included(controller)
|
156
|
-
|
184
|
+
entity = if defined?(Rails::VERSION::MAJOR) && (Rails::VERSION::MAJOR >= 4)
|
185
|
+
'action'
|
186
|
+
else
|
187
|
+
'filter'
|
188
|
+
end
|
189
|
+
|
190
|
+
controller.send :"around_#{entity}", :_catch_soap_errors
|
157
191
|
controller.send :helper, :wash_out
|
158
|
-
controller.send :
|
159
|
-
|
160
|
-
controller.send :
|
161
|
-
|
162
|
-
controller.send :skip_before_filter, :verify_authenticity_token
|
192
|
+
controller.send :"before_#{entity}", :_authenticate_wsse, :if => :soap_action?
|
193
|
+
controller.send :"before_#{entity}", :_map_soap_parameters, :if => :soap_action?
|
194
|
+
controller.send :"before_#{entity}", :_map_soap_headers, :if => :soap_action?
|
195
|
+
controller.send :"skip_before_#{entity}", :verify_authenticity_token, :raise => false
|
163
196
|
end
|
164
197
|
|
165
|
-
def self.deep_select(
|
166
|
-
|
198
|
+
def self.deep_select(collection, result=[], &blk)
|
199
|
+
values = collection.respond_to?(:values) ? collection.values : collection
|
200
|
+
result += values.select(&blk)
|
167
201
|
|
168
|
-
|
169
|
-
|
202
|
+
values.each do |value|
|
203
|
+
if value.is_a?(Hash) || value.is_a?(Array)
|
204
|
+
result = deep_select(value, result, &blk)
|
205
|
+
end
|
170
206
|
end
|
171
207
|
|
172
208
|
result
|
173
209
|
end
|
174
210
|
|
175
|
-
def self.deep_replace_href(
|
176
|
-
return
|
211
|
+
def self.deep_replace_href(element, replace)
|
212
|
+
return element unless element.is_a?(Array) || element.is_a?(Hash)
|
177
213
|
|
178
|
-
|
179
|
-
|
214
|
+
if element.is_a?(Array) # Traverse arrays
|
215
|
+
return element.map{|x| deep_replace_href(x, replace)}
|
180
216
|
end
|
181
217
|
|
182
|
-
|
218
|
+
if element.has_key?(:@href) # Replace needle and traverse replacement
|
219
|
+
return deep_replace_href(replace[element[:@href]], replace)
|
220
|
+
end
|
221
|
+
|
222
|
+
element.each do |key, value| # Traverse hashes
|
223
|
+
element[key] = deep_replace_href(value, replace)
|
224
|
+
end
|
225
|
+
|
226
|
+
element
|
183
227
|
end
|
184
228
|
|
185
229
|
private
|
230
|
+
def soap_action?
|
231
|
+
soap_action.present?
|
232
|
+
end
|
186
233
|
|
187
234
|
def action_spec
|
188
235
|
self.class.soap_actions[soap_action]
|
189
236
|
end
|
190
237
|
|
238
|
+
def request_input_tag
|
239
|
+
action_spec[:request_tag]
|
240
|
+
end
|
241
|
+
|
191
242
|
def soap_action
|
192
243
|
request.env['wash_out.soap_action']
|
193
244
|
end
|
194
245
|
|
195
246
|
def xml_data
|
196
|
-
|
197
|
-
xml_data =
|
198
|
-
xml_data
|
247
|
+
envelope = request.env['wash_out.soap_data'].values_at(:envelope, :Envelope).compact.first
|
248
|
+
xml_data = envelope.values_at(:body, :Body).compact.first || {}
|
249
|
+
return xml_data if soap_config.wsdl_style == "document"
|
250
|
+
xml_data = xml_data.values_at(soap_action.underscore.to_sym, soap_action.to_sym, request_input_tag.to_sym).compact.first || {}
|
251
|
+
end
|
252
|
+
|
253
|
+
def xml_header_data
|
254
|
+
envelope = request.env['wash_out.soap_data'].values_at(:envelope, :Envelope).compact.first
|
255
|
+
header_data = envelope.values_at(:header, :Header).compact.first || {}
|
199
256
|
end
|
200
257
|
|
201
258
|
end
|
data/lib/wash_out/param.rb
CHANGED
@@ -7,6 +7,7 @@ module WashOut
|
|
7
7
|
attr_accessor :multiplied
|
8
8
|
attr_accessor :value
|
9
9
|
attr_accessor :source_class
|
10
|
+
attr_accessor :soap_config
|
10
11
|
|
11
12
|
# Defines a WSDL parameter with name +name+ and type specifier +type+.
|
12
13
|
# The type specifier format is described in #parse_def.
|
@@ -63,6 +64,7 @@ module WashOut
|
|
63
64
|
operation = case type
|
64
65
|
when 'string'; :to_s
|
65
66
|
when 'integer'; :to_i
|
67
|
+
when 'long'; :to_i
|
66
68
|
when 'double'; :to_f
|
67
69
|
when 'boolean'; lambda{|dat| dat === "0" ? false : !!dat}
|
68
70
|
when 'date'; :to_date
|
@@ -160,10 +162,19 @@ module WashOut
|
|
160
162
|
def flat_copy
|
161
163
|
copy = self.class.new(@soap_config, @name, @type.to_sym, @multiplied)
|
162
164
|
copy.raw_name = raw_name
|
163
|
-
copy.source_class =
|
165
|
+
copy.source_class = source_class
|
164
166
|
copy
|
165
167
|
end
|
166
168
|
|
169
|
+
def attribute?
|
170
|
+
name[0] == "@"
|
171
|
+
end
|
172
|
+
|
173
|
+
def attr_name
|
174
|
+
raise 'Not attribute' unless attribute?
|
175
|
+
name[1..-1]
|
176
|
+
end
|
177
|
+
|
167
178
|
private
|
168
179
|
|
169
180
|
# Used to load an entire structure.
|
@@ -178,7 +189,8 @@ module WashOut
|
|
178
189
|
# RUBY18 Enumerable#each_with_object is better, but 1.9 only.
|
179
190
|
@map.map do |param|
|
180
191
|
if data.has_key? param.raw_name
|
181
|
-
|
192
|
+
param_name = param.attribute? ? param.attr_name : param.raw_name
|
193
|
+
struct[param_name] = yield param, data, param.raw_name
|
182
194
|
end
|
183
195
|
end
|
184
196
|
|
data/lib/wash_out/router.rb
CHANGED
@@ -4,6 +4,37 @@ module WashOut
|
|
4
4
|
# This class is a Rack middleware used to route SOAP requests to a proper
|
5
5
|
# action of a given SOAP controller.
|
6
6
|
class Router
|
7
|
+
def self.lookup_soap_routes(controller_name, routes, path=[], &block)
|
8
|
+
routes.each do |x|
|
9
|
+
defaults = x.defaults
|
10
|
+
defaults = defaults[:defaults] if defaults.include?(:defaults) # Rails 5
|
11
|
+
if defaults[:controller] == controller_name && defaults[:action] == 'soap'
|
12
|
+
yield path+[x]
|
13
|
+
end
|
14
|
+
|
15
|
+
app = x.app
|
16
|
+
app = app.app if app.respond_to?(:app)
|
17
|
+
if app.respond_to?(:routes)
|
18
|
+
lookup_soap_routes(controller_name, app.routes.routes, path+[x], &block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.url(request, controller_name)
|
24
|
+
lookup_soap_routes(controller_name, Rails.application.routes.routes) do |routes|
|
25
|
+
|
26
|
+
path = if routes.first.respond_to?(:optimized_path) # Rails 4
|
27
|
+
routes.map(&:optimized_path)
|
28
|
+
elsif routes.first.path.respond_to?(:build_formatter) # Rails 5
|
29
|
+
routes.map{|x| x.path.build_formatter.evaluate(nil)}
|
30
|
+
else
|
31
|
+
routes.map{|x| x.format({})} # Rails 3.2
|
32
|
+
end
|
33
|
+
|
34
|
+
return request.protocol + request.host_with_port + path.flatten.join('')
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
7
38
|
def initialize(controller_name)
|
8
39
|
@controller_name = "#{controller_name.to_s}_controller".camelize
|
9
40
|
end
|
@@ -17,15 +48,13 @@ module WashOut
|
|
17
48
|
|
18
49
|
soap_action = controller.soap_config.soap_action_routing ? env['HTTP_SOAPACTION'].to_s.gsub(/^"(.*)"$/, '\1')
|
19
50
|
: ''
|
20
|
-
|
21
51
|
if soap_action.blank?
|
22
52
|
parsed_soap_body = nori(controller.soap_config.snakecase_input).parse(soap_body env)
|
23
53
|
return nil if parsed_soap_body.blank?
|
24
54
|
|
25
|
-
soap_action = parsed_soap_body
|
26
|
-
|
27
|
-
|
28
|
-
.keys.first.to_s
|
55
|
+
soap_action = parsed_soap_body.values_at(:envelope, :Envelope).try(:compact).try(:first)
|
56
|
+
soap_action = soap_action.values_at(:body, :Body).try(:compact).try(:first) if soap_action
|
57
|
+
soap_action = soap_action.keys.first.to_s if soap_action
|
29
58
|
end
|
30
59
|
|
31
60
|
# RUBY18 1.8 does not have force_encoding.
|
@@ -52,18 +81,17 @@ module WashOut
|
|
52
81
|
end
|
53
82
|
|
54
83
|
def soap_body(env)
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
84
|
+
body = env['rack.input']
|
85
|
+
body.rewind if body.respond_to? :rewind
|
86
|
+
body.respond_to?(:string) ? body.string : body.read
|
87
|
+
ensure
|
88
|
+
body.rewind if body.respond_to? :rewind
|
60
89
|
end
|
61
90
|
|
62
91
|
def parse_soap_parameters(env)
|
63
92
|
return env['wash_out.soap_data'] if env['wash_out.soap_data']
|
64
|
-
|
65
93
|
env['wash_out.soap_data'] = nori(controller.soap_config.snakecase_input).parse(soap_body env)
|
66
|
-
references = WashOut::Dispatcher.deep_select(env['wash_out.soap_data']){|
|
94
|
+
references = WashOut::Dispatcher.deep_select(env['wash_out.soap_data']){|v| v.is_a?(Hash) && v.has_key?(:@id)}
|
67
95
|
|
68
96
|
unless references.blank?
|
69
97
|
replaces = {}; references.each{|r| replaces['#'+r[:@id]] = r}
|
@@ -76,19 +104,21 @@ module WashOut
|
|
76
104
|
def call(env)
|
77
105
|
@controller = @controller_name.constantize
|
78
106
|
|
79
|
-
soap_action
|
80
|
-
return [200, {}, ['OK']] if soap_action.blank?
|
107
|
+
soap_action = parse_soap_action(env)
|
81
108
|
|
82
|
-
|
83
|
-
|
84
|
-
action_spec = controller.soap_actions[soap_action]
|
85
|
-
|
86
|
-
if action_spec
|
87
|
-
action = action_spec[:to]
|
109
|
+
action = if soap_action.blank?
|
110
|
+
'_invalid_request'
|
88
111
|
else
|
89
|
-
|
112
|
+
soap_parameters = parse_soap_parameters(env)
|
113
|
+
action_spec = controller.soap_actions[soap_action]
|
114
|
+
|
115
|
+
if action_spec
|
116
|
+
action_spec[:to]
|
117
|
+
else
|
118
|
+
'_invalid_action'
|
119
|
+
end
|
90
120
|
end
|
91
|
-
|
121
|
+
env["action_dispatch.request.content_type"] = Mime[:soap]
|
92
122
|
controller.action(action).call(env)
|
93
123
|
end
|
94
124
|
end
|
data/lib/wash_out/soap.rb
CHANGED
@@ -13,7 +13,15 @@ module WashOut
|
|
13
13
|
#
|
14
14
|
# An optional option :to can be passed to allow for names of SOAP actions
|
15
15
|
# which are not valid Ruby function names.
|
16
|
+
# There is also an optional :header_return option to specify the format of the
|
17
|
+
# SOAP response's header tag (<env:Header></env:Header>). If unspecified, there will
|
18
|
+
# be no header tag in the response.
|
16
19
|
def soap_action(action, options={})
|
20
|
+
if options[:as].present?
|
21
|
+
options[:to] ||= action
|
22
|
+
action = options[:as]
|
23
|
+
end
|
24
|
+
|
17
25
|
if action.is_a?(Symbol)
|
18
26
|
if soap_config.camelize_wsdl.to_s == 'lower'
|
19
27
|
options[:to] ||= action.to_s
|
@@ -28,9 +36,12 @@ module WashOut
|
|
28
36
|
default_response_tag = soap_config.camelize_wsdl ? 'Response' : '_response'
|
29
37
|
default_response_tag = action+default_response_tag
|
30
38
|
|
39
|
+
|
31
40
|
self.soap_actions[action] = options.merge(
|
32
41
|
:in => WashOut::Param.parse_def(soap_config, options[:args]),
|
42
|
+
:request_tag => options[:as] || action,
|
33
43
|
:out => WashOut::Param.parse_def(soap_config, options[:return]),
|
44
|
+
:header_out => options[:header_return].present? ? WashOut::Param.parse_def(soap_config, options[:header_return]) : nil,
|
34
45
|
:to => options[:to] || action,
|
35
46
|
:response_tag => options[:response_tag] || default_response_tag
|
36
47
|
)
|
data/lib/wash_out/version.rb
CHANGED
data/lib/wash_out/wsse.rb
CHANGED
@@ -49,8 +49,8 @@ module WashOut
|
|
49
49
|
def matches_expected_digest?(password)
|
50
50
|
nonce = @username_token.values_at(:nonce, :Nonce).compact.first
|
51
51
|
timestamp = @username_token.values_at(:created, :Created).compact.first
|
52
|
-
|
53
52
|
return false if nonce.nil? || timestamp.nil?
|
53
|
+
timestamp = timestamp.to_datetime
|
54
54
|
|
55
55
|
# Token should not be accepted if timestamp is older than 5 minutes ago
|
56
56
|
# http://www.oasis-open.org/committees/download.php/16782/wss-v1.1-spec-os-UsernameTokenProfile.pdf
|
@@ -62,11 +62,11 @@ module WashOut
|
|
62
62
|
flavors = Array.new
|
63
63
|
|
64
64
|
# Ruby / Savon
|
65
|
-
token = nonce + timestamp.
|
65
|
+
token = nonce + timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") + expected_password
|
66
66
|
flavors << Base64.encode64(Digest::SHA1.hexdigest(token)).chomp!
|
67
67
|
|
68
68
|
# Java
|
69
|
-
token = Base64.decode64(nonce) + timestamp.
|
69
|
+
token = Base64.decode64(nonce) + timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") + expected_password
|
70
70
|
flavors << Base64.encode64(Digest::SHA1.digest(token)).chomp!
|
71
71
|
|
72
72
|
flavors.each do |f|
|
data/lib/wash_out.rb
CHANGED
@@ -11,15 +11,28 @@ require 'wash_out/model'
|
|
11
11
|
require 'wash_out/wsse'
|
12
12
|
require 'wash_out/middleware'
|
13
13
|
|
14
|
+
module WashOut
|
15
|
+
def self.root
|
16
|
+
File.expand_path '../..', __FILE__
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
14
20
|
module ActionDispatch::Routing
|
15
21
|
class Mapper
|
16
22
|
# Adds the routes for a SOAP endpoint at +controller+.
|
17
23
|
def wash_out(controller_name, options={})
|
18
|
-
|
19
|
-
|
24
|
+
if @scope
|
25
|
+
scope_frame = @scope.respond_to?(:frame) ? @scope.frame : @scope
|
26
|
+
options.each{ |key, value| scope_frame[key] = value }
|
27
|
+
end
|
20
28
|
|
21
|
-
|
22
|
-
|
29
|
+
controller_class_name = [scope_frame[:module], controller_name].compact.join("/").underscore
|
30
|
+
|
31
|
+
match "#{controller_name}/wsdl" => "#{controller_name}#_generate_wsdl", :via => :get, :format => false,
|
32
|
+
:as => "#{controller_class_name}_wsdl"
|
33
|
+
match "#{controller_name}/action" => WashOut::Router.new(controller_class_name), :via => [:get, :post],
|
34
|
+
:defaults => { :controller => controller_class_name, :action => 'soap' }, :format => false,
|
35
|
+
:as => "#{controller_class_name}_soap"
|
23
36
|
end
|
24
37
|
end
|
25
38
|
end
|
@@ -31,7 +44,7 @@ ActionController::Renderers.add :soap do |what, options|
|
|
31
44
|
_render_soap(what, options)
|
32
45
|
end
|
33
46
|
|
34
|
-
ActionController::
|
47
|
+
ActionController::Metal.class_eval do
|
35
48
|
|
36
49
|
# Define a SOAP service. The function has no required +options+:
|
37
50
|
# but allow any of :parser, :namespace, :wsdl_style, :snakecase_input,
|
@@ -45,3 +58,17 @@ ActionController::Base.class_eval do
|
|
45
58
|
self.soap_config = options
|
46
59
|
end
|
47
60
|
end
|
61
|
+
|
62
|
+
if Rails::VERSION::MAJOR >= 5
|
63
|
+
module ActionController
|
64
|
+
module ApiRendering
|
65
|
+
include ActionView::Rendering
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
ActiveSupport.on_load :action_controller do
|
70
|
+
if self == ActionController::API
|
71
|
+
include ActionController::Helpers
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
|
2
|
+
<s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
4
|
+
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
5
|
+
<parent href="#id1" />
|
6
|
+
<q2:child id="id1" xsi:type="q2:child" xmlns:q2="urn:FakeService">
|
7
|
+
<first_list href="#id2" />
|
8
|
+
<second_list href="#id3" />
|
9
|
+
</q2:child>
|
10
|
+
<q3:Array id="id2" q3:arrayType="xsd:int[1]" xmlns:q3="http://schemas.xmlsoap.org/soap/encoding/">
|
11
|
+
<Item>1</Item>
|
12
|
+
<Item>2</Item>
|
13
|
+
</q3:Array>
|
14
|
+
<q4:Array id="id3" q4:arrayType="xsd:int[1]" xmlns:q4="http://schemas.xmlsoap.org/soap/encoding/">
|
15
|
+
<Item>11</Item>
|
16
|
+
<Item>22</Item>
|
17
|
+
</q4:Array>
|
18
|
+
</s:Body>
|
19
|
+
</s:Envelope>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
|
2
|
+
<s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
4
|
+
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
5
|
+
<list href="#id1" />
|
6
|
+
<q1:Array id="id1" q1:arrayType="xsd:int[1]" xmlns:q1="http://schemas.xmlsoap.org/soap/encoding/">
|
7
|
+
<Item>1</Item>
|
8
|
+
<Item>2</Item>
|
9
|
+
</q1:Array>
|
10
|
+
</s:Body>
|
11
|
+
</s:Envelope>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
|
2
|
+
<s:Body s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
|
3
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
4
|
+
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
5
|
+
<first_list href="#id1" />
|
6
|
+
<second_list href="#id2" />
|
7
|
+
<q1:Array id="id1" q1:arrayType="xsd:int[1]" xmlns:q1="http://schemas.xmlsoap.org/soap/encoding/">
|
8
|
+
<Item>1</Item>
|
9
|
+
<Item>2</Item>
|
10
|
+
</q1:Array>
|
11
|
+
<q2:Array id="id2" q2:arrayType="xsd:int[1]" xmlns:q2="http://schemas.xmlsoap.org/soap/encoding/">
|
12
|
+
<Item>11</Item>
|
13
|
+
<Item>22</Item>
|
14
|
+
</q2:Array>
|
15
|
+
</s:Body>
|
16
|
+
</s:Envelope>
|