wash_out 0.9.0 → 0.11.0.beta.1
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 +3 -1
- data/.travis.yml +31 -3
- data/Appraisals +17 -8
- data/Gemfile +2 -2
- data/README.md +68 -8
- data/Rakefile +6 -7
- data/app/helpers/wash_out_helper.rb +59 -24
- data/app/views/{wash_with_soap → wash_out}/document/error.builder +1 -1
- data/app/views/{wash_with_soap → wash_out}/document/response.builder +1 -3
- data/app/views/{wash_with_soap → wash_out}/document/wsdl.builder +16 -16
- data/app/views/{wash_with_soap → wash_out}/rpc/error.builder +1 -1
- data/app/views/{wash_with_soap → wash_out}/rpc/response.builder +1 -3
- data/app/views/{wash_with_soap → wash_out}/rpc/wsdl.builder +17 -17
- 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/lib/wash_out/dispatcher.rb +94 -48
- data/lib/wash_out/model.rb +1 -1
- data/lib/wash_out/param.rb +14 -1
- data/lib/wash_out/router.rb +46 -18
- data/lib/wash_out/soap.rb +5 -3
- data/lib/wash_out/soap_config.rb +2 -0
- data/lib/wash_out/version.rb +1 -1
- data/lib/wash_out/wsse.rb +27 -6
- data/lib/wash_out.rb +18 -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 +135 -13
- 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 +50 -0
- data/spec/lib/wash_out/type_spec.rb +9 -9
- data/spec/lib/wash_out_spec.rb +196 -88
- data/spec/spec_helper.rb +24 -4
- metadata +26 -17
data/lib/wash_out/dispatcher.rb
CHANGED
@@ -5,13 +5,19 @@ module WashOut
|
|
5
5
|
module Dispatcher
|
6
6
|
# A SOAPError exception can be raised to return a correct SOAP error
|
7
7
|
# response.
|
8
|
-
class SOAPError < Exception
|
8
|
+
class SOAPError < Exception
|
9
|
+
attr_accessor :code
|
10
|
+
def initialize(message, code=nil)
|
11
|
+
super(message)
|
12
|
+
@code = code
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
9
16
|
class ProgrammerError < Exception; end
|
10
17
|
|
11
18
|
def _authenticate_wsse
|
12
|
-
|
13
19
|
begin
|
14
|
-
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
|
15
21
|
xml_security = xml_security.values_at(:header, :Header).compact.first
|
16
22
|
xml_security = xml_security.values_at(:security, :Security).compact.first
|
17
23
|
username_token = xml_security.values_at(:username_token, :UsernameToken).compact.first
|
@@ -25,32 +31,27 @@ module WashOut
|
|
25
31
|
end
|
26
32
|
|
27
33
|
def _map_soap_parameters
|
34
|
+
@_params = _load_params action_spec[:in],
|
35
|
+
_strip_empty_nodes(action_spec[:in], xml_data)
|
36
|
+
end
|
28
37
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
xml_data = xml_data.values_at(:body, :Body).compact.first
|
34
|
-
xml_data = xml_data.values_at(soap_action.underscore.to_sym,
|
35
|
-
soap_action.to_sym).compact.first || {}
|
38
|
+
def _strip_empty_nodes(params, hash)
|
39
|
+
hash.keys.each do |key|
|
40
|
+
param = params.detect { |a| a.raw_name.to_s == key.to_s }
|
41
|
+
next if !(param && hash[key].is_a?(Hash))
|
36
42
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
value = hash[key].delete_if{|k, v| key.to_s[0] == '@'}
|
43
|
+
value = hash[key].delete_if do |k, _|
|
44
|
+
k.to_s[0] == '@' && !param.map.detect { |a| a.raw_name.to_s == k.to_s }
|
45
|
+
end
|
41
46
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
end
|
47
|
-
end
|
47
|
+
if value.length > 0
|
48
|
+
hash[key] = _strip_empty_nodes param.map, value
|
49
|
+
else
|
50
|
+
hash[key] = nil
|
48
51
|
end
|
52
|
+
end
|
49
53
|
|
50
|
-
|
51
|
-
}
|
52
|
-
xml_data = strip_empty_nodes.call(xml_data)
|
53
|
-
@_params = _load_params(action_spec[:in], xml_data)
|
54
|
+
hash
|
54
55
|
end
|
55
56
|
|
56
57
|
# Creates the final parameter hash based on the request spec and xml_data from the request
|
@@ -67,12 +68,11 @@ module WashOut
|
|
67
68
|
|
68
69
|
# This action generates the WSDL for defined SOAP methods.
|
69
70
|
def _generate_wsdl
|
70
|
-
|
71
71
|
@map = self.class.soap_actions
|
72
72
|
@namespace = soap_config.namespace
|
73
|
-
@name = controller_path
|
73
|
+
@name = controller_path
|
74
74
|
|
75
|
-
render :template => "
|
75
|
+
render :template => "wash_out/#{soap_config.wsdl_style}/wsdl", :layout => false,
|
76
76
|
:content_type => 'text/xml'
|
77
77
|
end
|
78
78
|
|
@@ -127,7 +127,7 @@ module WashOut
|
|
127
127
|
return result_spec
|
128
128
|
}
|
129
129
|
|
130
|
-
render :template => "
|
130
|
+
render :template => "wash_out/#{soap_config.wsdl_style}/response",
|
131
131
|
:layout => false,
|
132
132
|
:locals => { :result => inject.call(result, @action_spec[:out]) },
|
133
133
|
:content_type => 'text/xml'
|
@@ -138,49 +138,95 @@ module WashOut
|
|
138
138
|
render_soap_error("Cannot find SOAP action mapping for #{request.env['wash_out.soap_action']}")
|
139
139
|
end
|
140
140
|
|
141
|
-
def
|
142
|
-
render_soap_error(
|
141
|
+
def _invalid_request
|
142
|
+
render_soap_error("Invalid SOAP request")
|
143
|
+
end
|
144
|
+
|
145
|
+
def _catch_soap_errors
|
146
|
+
yield
|
147
|
+
rescue SOAPError => error
|
148
|
+
render_soap_error(error.message, error.code)
|
143
149
|
end
|
144
150
|
|
145
151
|
# Render a SOAP error response.
|
146
152
|
#
|
147
153
|
# Rails do not support sequental rescue_from handling, that is, rescuing an
|
148
154
|
# exception from a rescue_from handler. Hence this function is a public API.
|
149
|
-
def render_soap_error(message)
|
150
|
-
render :template => "
|
155
|
+
def render_soap_error(message, code=nil)
|
156
|
+
render :template => "wash_out/#{soap_config.wsdl_style}/error", :status => 500,
|
151
157
|
:layout => false,
|
152
|
-
:locals => { :error_message => message },
|
158
|
+
:locals => { :error_message => message, :error_code => (code || 'Server') },
|
153
159
|
:content_type => 'text/xml'
|
154
160
|
end
|
155
161
|
|
156
162
|
def self.included(controller)
|
157
|
-
|
163
|
+
entity = if defined?(Rails::VERSION::MAJOR) && (Rails::VERSION::MAJOR >= 4)
|
164
|
+
'action'
|
165
|
+
else
|
166
|
+
'filter'
|
167
|
+
end
|
168
|
+
|
169
|
+
controller.send :"around_#{entity}", :_catch_soap_errors
|
158
170
|
controller.send :helper, :wash_out
|
159
|
-
controller.send :
|
160
|
-
|
161
|
-
controller.send :
|
162
|
-
:_generate_wsdl, :_invalid_action ]
|
163
|
-
controller.send :skip_before_filter, :verify_authenticity_token
|
171
|
+
controller.send :"before_#{entity}", :_authenticate_wsse, :if => :soap_action?
|
172
|
+
controller.send :"before_#{entity}", :_map_soap_parameters, :if => :soap_action?
|
173
|
+
controller.send :"skip_before_#{entity}", :verify_authenticity_token
|
164
174
|
end
|
165
175
|
|
166
|
-
def self.deep_select(
|
167
|
-
|
176
|
+
def self.deep_select(collection, result=[], &blk)
|
177
|
+
values = collection.respond_to?(:values) ? collection.values : collection
|
178
|
+
result += values.select(&blk)
|
168
179
|
|
169
|
-
|
170
|
-
|
180
|
+
values.each do |value|
|
181
|
+
if value.is_a?(Hash) || value.is_a?(Array)
|
182
|
+
result = deep_select(value, result, &blk)
|
183
|
+
end
|
171
184
|
end
|
172
185
|
|
173
186
|
result
|
174
187
|
end
|
175
188
|
|
176
|
-
def self.deep_replace_href(
|
177
|
-
return
|
189
|
+
def self.deep_replace_href(element, replace)
|
190
|
+
return element unless element.is_a?(Array) || element.is_a?(Hash)
|
178
191
|
|
179
|
-
|
180
|
-
|
192
|
+
if element.is_a?(Array) # Traverse arrays
|
193
|
+
return element.map{|x| deep_replace_href(x, replace)}
|
181
194
|
end
|
182
195
|
|
183
|
-
|
196
|
+
if element.has_key?(:@href) # Replace needle and traverse replacement
|
197
|
+
return deep_replace_href(replace[element[:@href]], replace)
|
198
|
+
end
|
199
|
+
|
200
|
+
element.each do |key, value| # Traverse hashes
|
201
|
+
element[key] = deep_replace_href(value, replace)
|
202
|
+
end
|
203
|
+
|
204
|
+
element
|
205
|
+
end
|
206
|
+
|
207
|
+
private
|
208
|
+
def soap_action?
|
209
|
+
soap_action.present?
|
184
210
|
end
|
211
|
+
|
212
|
+
def action_spec
|
213
|
+
self.class.soap_actions[soap_action]
|
214
|
+
end
|
215
|
+
|
216
|
+
def request_input_tag
|
217
|
+
action_spec[:request_tag]
|
218
|
+
end
|
219
|
+
|
220
|
+
def soap_action
|
221
|
+
request.env['wash_out.soap_action']
|
222
|
+
end
|
223
|
+
|
224
|
+
def xml_data
|
225
|
+
xml_data = request.env['wash_out.soap_data'].values_at(:envelope, :Envelope).compact.first
|
226
|
+
xml_data = xml_data.values_at(:body, :Body).compact.first || {}
|
227
|
+
return xml_data if soap_config.wsdl_style == "document"
|
228
|
+
xml_data = xml_data.values_at(soap_action.underscore.to_sym, soap_action.to_sym, request_input_tag.to_sym).compact.first || {}
|
229
|
+
end
|
230
|
+
|
185
231
|
end
|
186
232
|
end
|
data/lib/wash_out/model.rb
CHANGED
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,9 +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
|
165
|
+
copy.source_class = source_class
|
163
166
|
copy
|
164
167
|
end
|
165
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
|
+
|
166
178
|
private
|
167
179
|
|
168
180
|
# Used to load an entire structure.
|
@@ -177,7 +189,8 @@ module WashOut
|
|
177
189
|
# RUBY18 Enumerable#each_with_object is better, but 1.9 only.
|
178
190
|
@map.map do |param|
|
179
191
|
if data.has_key? param.raw_name
|
180
|
-
|
192
|
+
param_name = param.attribute? ? param.attr_name : param.raw_name
|
193
|
+
struct[param_name] = yield param, data, param.raw_name
|
181
194
|
end
|
182
195
|
end
|
183
196
|
|
data/lib/wash_out/router.rb
CHANGED
@@ -4,6 +4,26 @@ 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.url(request, controller_name)
|
8
|
+
route = Rails.application.routes.routes.select do |x|
|
9
|
+
defaults = x.defaults
|
10
|
+
defaults = defaults[:defaults] if defaults.include?(:defaults) # Rails 5
|
11
|
+
defaults[:controller] == controller_name && defaults[:action] == 'soap'
|
12
|
+
end.first
|
13
|
+
|
14
|
+
path = if route.respond_to?(:optimized_path) # Rails 4
|
15
|
+
route.optimized_path
|
16
|
+
elsif route.path.respond_to?(:build_formatter) # Rails 5
|
17
|
+
route.path.build_formatter.evaluate(nil)
|
18
|
+
else
|
19
|
+
route.format({}) # Rails 3.2
|
20
|
+
end
|
21
|
+
|
22
|
+
path = path.join('') if path.is_a?(Array)
|
23
|
+
|
24
|
+
request.protocol + request.host_with_port + path
|
25
|
+
end
|
26
|
+
|
7
27
|
def initialize(controller_name)
|
8
28
|
@controller_name = "#{controller_name.to_s}_controller".camelize
|
9
29
|
end
|
@@ -15,13 +35,15 @@ module WashOut
|
|
15
35
|
def parse_soap_action(env)
|
16
36
|
return env['wash_out.soap_action'] if env['wash_out.soap_action']
|
17
37
|
|
18
|
-
soap_action = env['HTTP_SOAPACTION'].to_s.gsub(/^"(.*)"$/, '\1')
|
19
|
-
|
38
|
+
soap_action = controller.soap_config.soap_action_routing ? env['HTTP_SOAPACTION'].to_s.gsub(/^"(.*)"$/, '\1')
|
39
|
+
: ''
|
20
40
|
if soap_action.blank?
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
41
|
+
parsed_soap_body = nori(controller.soap_config.snakecase_input).parse(soap_body env)
|
42
|
+
return nil if parsed_soap_body.blank?
|
43
|
+
|
44
|
+
soap_action = parsed_soap_body.values_at(:envelope, :Envelope).try(:compact).try(:first)
|
45
|
+
soap_action = soap_action.values_at(:body, :Body).try(:compact).try(:first) if soap_action
|
46
|
+
soap_action = soap_action.keys.first.to_s if soap_action
|
25
47
|
end
|
26
48
|
|
27
49
|
# RUBY18 1.8 does not have force_encoding.
|
@@ -41,22 +63,24 @@ module WashOut
|
|
41
63
|
:strip_namespaces => true,
|
42
64
|
:advanced_typecasting => true,
|
43
65
|
:convert_tags_to => (
|
44
|
-
snakecase ? lambda { |tag| tag.snakecase.to_sym }
|
66
|
+
snakecase ? lambda { |tag| tag.snakecase.to_sym }
|
45
67
|
: lambda { |tag| tag.to_sym }
|
46
68
|
)
|
47
69
|
)
|
48
70
|
end
|
49
71
|
|
50
72
|
def soap_body(env)
|
51
|
-
|
52
|
-
|
73
|
+
body = env['rack.input']
|
74
|
+
body.rewind if body.respond_to? :rewind
|
75
|
+
body.respond_to?(:string) ? body.string : body.read
|
76
|
+
ensure
|
77
|
+
body.rewind if body.respond_to? :rewind
|
53
78
|
end
|
54
79
|
|
55
80
|
def parse_soap_parameters(env)
|
56
81
|
return env['wash_out.soap_data'] if env['wash_out.soap_data']
|
57
|
-
|
58
82
|
env['wash_out.soap_data'] = nori(controller.soap_config.snakecase_input).parse(soap_body env)
|
59
|
-
references = WashOut::Dispatcher.deep_select(env['wash_out.soap_data']){|
|
83
|
+
references = WashOut::Dispatcher.deep_select(env['wash_out.soap_data']){|v| v.is_a?(Hash) && v.has_key?(:@id)}
|
60
84
|
|
61
85
|
unless references.blank?
|
62
86
|
replaces = {}; references.each{|r| replaces['#'+r[:@id]] = r}
|
@@ -69,15 +93,19 @@ module WashOut
|
|
69
93
|
def call(env)
|
70
94
|
@controller = @controller_name.constantize
|
71
95
|
|
72
|
-
soap_action
|
73
|
-
soap_parameters = parse_soap_parameters(env)
|
74
|
-
|
75
|
-
action_spec = controller.soap_actions[soap_action]
|
96
|
+
soap_action = parse_soap_action(env)
|
76
97
|
|
77
|
-
if
|
78
|
-
|
98
|
+
action = if soap_action.blank?
|
99
|
+
'_invalid_request'
|
79
100
|
else
|
80
|
-
|
101
|
+
soap_parameters = parse_soap_parameters(env)
|
102
|
+
action_spec = controller.soap_actions[soap_action]
|
103
|
+
|
104
|
+
if action_spec
|
105
|
+
action_spec[:to]
|
106
|
+
else
|
107
|
+
'_invalid_action'
|
108
|
+
end
|
81
109
|
end
|
82
110
|
|
83
111
|
controller.action(action).call(env)
|
data/lib/wash_out/soap.rb
CHANGED
@@ -26,20 +26,22 @@ module WashOut
|
|
26
26
|
end
|
27
27
|
|
28
28
|
default_response_tag = soap_config.camelize_wsdl ? 'Response' : '_response'
|
29
|
-
default_response_tag =
|
29
|
+
default_response_tag = action+default_response_tag
|
30
30
|
|
31
|
-
self.soap_actions[action] =
|
31
|
+
self.soap_actions[action] = options.merge(
|
32
32
|
:in => WashOut::Param.parse_def(soap_config, options[:args]),
|
33
|
+
:request_tag => options[:as] || action,
|
33
34
|
:out => WashOut::Param.parse_def(soap_config, options[:return]),
|
34
35
|
:to => options[:to] || action,
|
35
36
|
:response_tag => options[:response_tag] || default_response_tag
|
36
|
-
|
37
|
+
)
|
37
38
|
end
|
38
39
|
end
|
39
40
|
|
40
41
|
included do
|
41
42
|
include WashOut::Configurable
|
42
43
|
include WashOut::Dispatcher
|
44
|
+
include WashOut::WsseParams
|
43
45
|
self.soap_actions = {}
|
44
46
|
end
|
45
47
|
end
|
data/lib/wash_out/soap_config.rb
CHANGED
data/lib/wash_out/version.rb
CHANGED
data/lib/wash_out/wsse.rb
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
module WashOut
|
2
|
+
|
3
|
+
module WsseParams
|
4
|
+
def wsse_username
|
5
|
+
if request.env['WSSE_TOKEN']
|
6
|
+
request.env['WSSE_TOKEN'].values_at(:username, :Username).compact.first
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
2
11
|
class Wsse
|
3
12
|
attr_reader :soap_config
|
4
13
|
def self.authenticate(soap_config, token)
|
@@ -18,7 +27,15 @@ module WashOut
|
|
18
27
|
end
|
19
28
|
|
20
29
|
def required?
|
21
|
-
!soap_config.wsse_username.blank?
|
30
|
+
!soap_config.wsse_username.blank? || auth_callback?
|
31
|
+
end
|
32
|
+
|
33
|
+
def auth_callback?
|
34
|
+
return !!soap_config.wsse_auth_callback && soap_config.wsse_auth_callback.respond_to?(:call) && soap_config.wsse_auth_callback.arity == 2
|
35
|
+
end
|
36
|
+
|
37
|
+
def perform_auth_callback(user, password)
|
38
|
+
soap_config.wsse_auth_callback.call(user, password)
|
22
39
|
end
|
23
40
|
|
24
41
|
def expected_user
|
@@ -32,8 +49,8 @@ module WashOut
|
|
32
49
|
def matches_expected_digest?(password)
|
33
50
|
nonce = @username_token.values_at(:nonce, :Nonce).compact.first
|
34
51
|
timestamp = @username_token.values_at(:created, :Created).compact.first
|
35
|
-
|
36
52
|
return false if nonce.nil? || timestamp.nil?
|
53
|
+
timestamp = timestamp.to_datetime
|
37
54
|
|
38
55
|
# Token should not be accepted if timestamp is older than 5 minutes ago
|
39
56
|
# http://www.oasis-open.org/committees/download.php/16782/wss-v1.1-spec-os-UsernameTokenProfile.pdf
|
@@ -45,11 +62,11 @@ module WashOut
|
|
45
62
|
flavors = Array.new
|
46
63
|
|
47
64
|
# Ruby / Savon
|
48
|
-
token = nonce + timestamp.
|
65
|
+
token = nonce + timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") + expected_password
|
49
66
|
flavors << Base64.encode64(Digest::SHA1.hexdigest(token)).chomp!
|
50
67
|
|
51
68
|
# Java
|
52
|
-
token = Base64.decode64(nonce) + timestamp.
|
69
|
+
token = Base64.decode64(nonce) + timestamp.strftime("%Y-%m-%dT%H:%M:%SZ") + expected_password
|
53
70
|
flavors << Base64.encode64(Digest::SHA1.digest(token)).chomp!
|
54
71
|
|
55
72
|
flavors.each do |f|
|
@@ -65,11 +82,15 @@ module WashOut
|
|
65
82
|
user = @username_token.values_at(:username, :Username).compact.first
|
66
83
|
password = @username_token.values_at(:password, :Password).compact.first
|
67
84
|
|
68
|
-
if (expected_user == user &&
|
85
|
+
if (expected_user == user && matches_expected_digest?(password))
|
69
86
|
return true
|
70
87
|
end
|
71
88
|
|
72
|
-
if
|
89
|
+
if auth_callback?
|
90
|
+
return perform_auth_callback(user, password)
|
91
|
+
end
|
92
|
+
|
93
|
+
if (expected_user == user && expected_password == password)
|
73
94
|
return true
|
74
95
|
end
|
75
96
|
|
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
|
@@ -44,4 +57,4 @@ ActionController::Base.class_eval do
|
|
44
57
|
include WashOut::SOAP
|
45
58
|
self.soap_config = options
|
46
59
|
end
|
47
|
-
end
|
60
|
+
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>
|