wash_out 0.8.4 → 0.9.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/README.md +18 -4
- data/app/helpers/wash_out_helper.rb +1 -1
- data/app/views/wash_with_soap/document/response.builder +1 -1
- data/app/views/wash_with_soap/document/wsdl.builder +2 -2
- data/app/views/wash_with_soap/rpc/response.builder +1 -1
- data/app/views/wash_with_soap/rpc/wsdl.builder +2 -2
- data/lib/wash_out/configurable.rb +41 -0
- data/lib/wash_out/dispatcher.rb +21 -15
- data/lib/wash_out/engine.rb +2 -42
- data/lib/wash_out/param.rb +16 -16
- data/lib/wash_out/router.rb +2 -2
- data/lib/wash_out/soap.rb +7 -5
- data/lib/wash_out/soap_config.rb +91 -0
- data/lib/wash_out/type.rb +5 -4
- data/lib/wash_out/version.rb +1 -1
- data/lib/wash_out/wsse.rb +8 -7
- data/lib/wash_out.rb +16 -5
- data/spec/lib/wash_out/dispatcher_spec.rb +6 -6
- data/spec/lib/wash_out/param_spec.rb +10 -5
- data/spec/lib/wash_out/type_spec.rb +2 -0
- data/spec/lib/wash_out_spec.rb +11 -27
- data/spec/spec_helper.rb +11 -6
- data/wash_out.gemspec +4 -1
- metadata +9 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4791d7a762e3d5a75e9f8d3233ddd7d0b10a240f
|
4
|
+
data.tar.gz: d0d43203c81135e8040258cf971bd5b849c95b2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 925b2b09044af493d24e94e63a089cd81e56797c04c52ed8555605e0c306f9e99acec82427d4c010092af825508addb61e7b11b7bc3d28100db0d5353075bcc9
|
7
|
+
data.tar.gz: 300d800215c4b1442e9eb85b1c07d67126b04b3d8cca50120072b5543e32d51f14db91d33fb7258aa8580c29942cc8518924dec2c63b5ebfd00e89479b509e09
|
data/README.md
CHANGED
@@ -22,6 +22,8 @@ In your Gemfile, add this line:
|
|
22
22
|
|
23
23
|
gem 'wash_out'
|
24
24
|
|
25
|
+
If you are upgrading from version < 0.8.5, replace `include WashOut::Soap` with `soap_service` at the controller level.
|
26
|
+
|
25
27
|
## Usage
|
26
28
|
|
27
29
|
A SOAP endpoint in WashOut is simply a Rails controller which includes the module WashOut::SOAP. Each SOAP
|
@@ -34,7 +36,7 @@ demonstrated.
|
|
34
36
|
```ruby
|
35
37
|
# app/controllers/rumbas_controller.rb
|
36
38
|
class RumbasController < ApplicationController
|
37
|
-
|
39
|
+
soap_service namespace: 'urn:WashOut'
|
38
40
|
|
39
41
|
# Simple case
|
40
42
|
soap_action "integer_to_string",
|
@@ -139,7 +141,8 @@ inside your interface declarations.
|
|
139
141
|
|
140
142
|
## Configuration
|
141
143
|
|
142
|
-
Use `config.wash_out...` inside your environment configuration to setup WashOut.
|
144
|
+
Use `config.wash_out...` inside your environment configuration to setup WashOut globally.
|
145
|
+
To override the values on a specific controller just add an override as part of the arguments to the `soap_service` method.
|
143
146
|
|
144
147
|
Available properties are:
|
145
148
|
|
@@ -149,7 +152,7 @@ Available properties are:
|
|
149
152
|
* **namespace**: SOAP namespace to use. Default is `urn:WashOut`.
|
150
153
|
* **snakecase**: *(DEPRECATED SINCE 0.4.0)* Determines if WashOut should modify parameters keys to snakecase. Default is `false`.
|
151
154
|
* **snakecase_input**: Determines if WashOut should modify parameters keys to snakecase. Default is `false`.
|
152
|
-
* **camelize_wsdl**: Determines if WashOut should camelize types within WSDL and responses. Default is `false`.
|
155
|
+
* **camelize_wsdl**: Determines if WashOut should camelize types within WSDL and responses. Supports `true` for CamelCase and `:lower` for camelCase. Default is `false`.
|
153
156
|
|
154
157
|
### Camelization
|
155
158
|
|
@@ -164,6 +167,17 @@ soap_action "foo" # this will be passed as is
|
|
164
167
|
|
165
168
|
* Boris Staal, [@inossidabile](http://staal.io)
|
166
169
|
|
170
|
+
## Contributors (in random order)
|
171
|
+
|
172
|
+
* Mikael Henriksson, [@mhenrixon](http://twitter.com/mhenrixon)
|
173
|
+
* Björn Nilsson [@Bjorn-Nilsson](https://github.com/Bjorn-Nilsson)
|
174
|
+
* Tobias Bielohlawek [@rngtng](https://github.com/rngtng)
|
175
|
+
* Francesco Negri [@dhinus](https://github.com/dhinus)
|
176
|
+
* Edgars Beigarts [@ebeigarts](https://github.com/ebeigarts)
|
177
|
+
* [Exad](https://github.com/exad) [@wknechtel](https://github.com/wknechtel) and [@☈king](https://github.com/rking)
|
178
|
+
* Mark Goris [@gorism](https://github.com/gorism)
|
179
|
+
* ... and [others](https://github.com/inossidabile/wash_out/graphs/contributors)
|
180
|
+
|
167
181
|
## License
|
168
182
|
|
169
|
-
It is free software, and may be redistributed under the terms of MIT license.
|
183
|
+
It is free software, and may be redistributed under the terms of MIT license.
|
@@ -3,7 +3,7 @@ xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envel
|
|
3
3
|
"xmlns:xsd" => 'http://www.w3.org/2001/XMLSchema',
|
4
4
|
"xmlns:tns" => @namespace do
|
5
5
|
xml.tag! "soap:Body" do
|
6
|
-
key = "tns:#{@operation}#{
|
6
|
+
key = "tns:#{@operation}#{controller.soap_config.camelize_wsdl ? 'Response' : '_response'}"
|
7
7
|
|
8
8
|
xml.tag! @action_spec[:response_tag] do
|
9
9
|
wsdl_data xml, result
|
@@ -23,7 +23,7 @@ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
|
|
23
23
|
@map.keys.each do |operation|
|
24
24
|
xml.operation :name => operation do
|
25
25
|
xml.input :message => "tns:#{operation}"
|
26
|
-
xml.output :message => "tns:#{operation}#{
|
26
|
+
xml.output :message => "tns:#{operation}#{controller.soap_config.camelize_wsdl ? 'Response' : '_response'}"
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -59,7 +59,7 @@ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
|
|
59
59
|
xml.part wsdl_occurence(p, false, :name => p.name, :type => p.namespaced_type)
|
60
60
|
end
|
61
61
|
end
|
62
|
-
xml.message :name => "#{operation}#{
|
62
|
+
xml.message :name => "#{operation}#{controller.soap_config.camelize_wsdl ? 'Response' : '_response'}" do
|
63
63
|
formats[:out].each do |p|
|
64
64
|
xml.part wsdl_occurence(p, false, :name => p.name, :type => p.namespaced_type)
|
65
65
|
end
|
@@ -4,7 +4,7 @@ xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envel
|
|
4
4
|
"xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance',
|
5
5
|
"xmlns:tns" => @namespace do
|
6
6
|
xml.tag! "soap:Body" do
|
7
|
-
key = "tns:#{@operation}#{
|
7
|
+
key = "tns:#{@operation}#{controller.soap_config.camelize_wsdl ? 'Response' : '_response'}"
|
8
8
|
|
9
9
|
xml.tag! @action_spec[:response_tag] do
|
10
10
|
wsdl_data xml, result
|
@@ -23,7 +23,7 @@ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
|
|
23
23
|
@map.keys.each do |operation|
|
24
24
|
xml.operation :name => operation do
|
25
25
|
xml.input :message => "tns:#{operation}"
|
26
|
-
xml.output :message => "tns:#{operation}#{
|
26
|
+
xml.output :message => "tns:#{operation}#{controller.soap_config.camelize_wsdl ? 'Response' : '_response'}"
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
@@ -59,7 +59,7 @@ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
|
|
59
59
|
xml.part wsdl_occurence(p, true, :name => p.name, :type => p.namespaced_type)
|
60
60
|
end
|
61
61
|
end
|
62
|
-
xml.message :name => "#{operation}#{
|
62
|
+
xml.message :name => "#{operation}#{controller.soap_config.camelize_wsdl ? 'Response' : '_response'}" do
|
63
63
|
formats[:out].each do |p|
|
64
64
|
xml.part wsdl_occurence(p, true, :name => p.name, :type => p.namespaced_type)
|
65
65
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module WashOut
|
2
|
+
module Configurable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
cattr_reader :soap_config
|
7
|
+
class_variable_set :@@soap_config, WashOut::SoapConfig.new({})
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
|
12
|
+
def soap_config=(obj)
|
13
|
+
|
14
|
+
unless obj.is_a?(Hash)
|
15
|
+
raise "Value needs to be a Hash."
|
16
|
+
end
|
17
|
+
|
18
|
+
if class_variable_defined?(:@@soap_config)
|
19
|
+
class_variable_get(:@@soap_config).configure obj
|
20
|
+
else
|
21
|
+
class_variable_set :@@soap_config, WashOut::SoapConfig.new(obj)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def soap_config=(obj)
|
27
|
+
|
28
|
+
unless obj.is_a?(Hash)
|
29
|
+
raise "Value needs to be a Hash."
|
30
|
+
end
|
31
|
+
|
32
|
+
class_eval do
|
33
|
+
if class_variable_defined?(:@@soap_config)
|
34
|
+
class_variable_get(:@@soap_config).configure obj
|
35
|
+
else
|
36
|
+
class_variable_set :@@soap_config, WashOut::SoapConfig.new(obj)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/wash_out/dispatcher.rb
CHANGED
@@ -12,14 +12,14 @@ module WashOut
|
|
12
12
|
|
13
13
|
# This filter parses the SOAP request and puts it into +params+ array.
|
14
14
|
def _parse_soap_parameters
|
15
|
-
|
16
|
-
|
15
|
+
|
16
|
+
nori_parser = Nori.new(
|
17
|
+
:parser => soap_config.parser,
|
17
18
|
:strip_namespaces => true,
|
18
19
|
:advanced_typecasting => true,
|
19
|
-
:convert_tags_to => (
|
20
|
-
: lambda { |tag| tag.to_sym } ))
|
20
|
+
:convert_tags_to => ( soap_config.snakecase_input ? lambda { |tag| tag.snakecase.to_sym } : lambda { |tag| tag.to_sym } ))
|
21
21
|
|
22
|
-
@_params =
|
22
|
+
@_params = nori_parser.parse(request.body.read)
|
23
23
|
references = WashOut::Dispatcher.deep_select(@_params){|k,v| v.is_a?(Hash) && v.has_key?(:@id)}
|
24
24
|
|
25
25
|
unless references.blank?
|
@@ -29,6 +29,7 @@ module WashOut
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def _authenticate_wsse
|
32
|
+
|
32
33
|
begin
|
33
34
|
xml_security = @_params.values_at(:envelope, :Envelope).compact.first
|
34
35
|
xml_security = xml_security.values_at(:header, :Header).compact.first
|
@@ -38,12 +39,13 @@ module WashOut
|
|
38
39
|
username_token = nil
|
39
40
|
end
|
40
41
|
|
41
|
-
WashOut::Wsse.authenticate username_token
|
42
|
+
WashOut::Wsse.authenticate soap_config, username_token
|
42
43
|
|
43
44
|
request.env['WSSE_TOKEN'] = username_token.with_indifferent_access unless username_token.blank?
|
44
45
|
end
|
45
46
|
|
46
47
|
def _map_soap_parameters
|
48
|
+
|
47
49
|
soap_action = request.env['wash_out.soap_action']
|
48
50
|
action_spec = self.class.soap_actions[soap_action]
|
49
51
|
|
@@ -55,7 +57,7 @@ module WashOut
|
|
55
57
|
strip_empty_nodes = lambda{|hash|
|
56
58
|
hash.keys.each do |key|
|
57
59
|
if hash[key].is_a? Hash
|
58
|
-
value = hash[key].delete_if{|
|
60
|
+
value = hash[key].delete_if{|k, v| key.to_s[0] == '@'}
|
59
61
|
|
60
62
|
if value.length > 0
|
61
63
|
hash[key] = strip_empty_nodes.call(value)
|
@@ -85,17 +87,18 @@ module WashOut
|
|
85
87
|
|
86
88
|
# This action generates the WSDL for defined SOAP methods.
|
87
89
|
def _generate_wsdl
|
90
|
+
|
88
91
|
@map = self.class.soap_actions
|
89
|
-
@namespace =
|
92
|
+
@namespace = soap_config.namespace
|
90
93
|
@name = controller_path.gsub('/', '_')
|
91
94
|
|
92
|
-
render :template => "wash_with_soap/#{
|
95
|
+
render :template => "wash_with_soap/#{soap_config.wsdl_style}/wsdl", :layout => false,
|
93
96
|
:content_type => 'text/xml'
|
94
97
|
end
|
95
98
|
|
96
99
|
# Render a SOAP response.
|
97
100
|
def _render_soap(result, options)
|
98
|
-
@namespace =
|
101
|
+
@namespace = soap_config.namespace
|
99
102
|
@operation = soap_action = request.env['wash_out.soap_action']
|
100
103
|
@action_spec = self.class.soap_actions[soap_action]
|
101
104
|
|
@@ -144,7 +147,7 @@ module WashOut
|
|
144
147
|
return result_spec
|
145
148
|
}
|
146
149
|
|
147
|
-
render :template => "wash_with_soap/#{
|
150
|
+
render :template => "wash_with_soap/#{soap_config.wsdl_style}/response",
|
148
151
|
:layout => false,
|
149
152
|
:locals => { :result => inject.call(result, @action_spec[:out]) },
|
150
153
|
:content_type => 'text/xml'
|
@@ -164,7 +167,7 @@ module WashOut
|
|
164
167
|
# Rails do not support sequental rescue_from handling, that is, rescuing an
|
165
168
|
# exception from a rescue_from handler. Hence this function is a public API.
|
166
169
|
def render_soap_error(message)
|
167
|
-
render :template => "wash_with_soap/#{
|
170
|
+
render :template => "wash_with_soap/#{soap_config.wsdl_style}/error", :status => 500,
|
168
171
|
:layout => false,
|
169
172
|
:locals => { :error_message => message },
|
170
173
|
:content_type => 'text/xml'
|
@@ -173,9 +176,12 @@ module WashOut
|
|
173
176
|
def self.included(controller)
|
174
177
|
controller.send :rescue_from, SOAPError, :with => :_render_soap_exception
|
175
178
|
controller.send :helper, :wash_out
|
176
|
-
controller.send :before_filter, :_parse_soap_parameters, :except => [
|
177
|
-
|
178
|
-
controller.send :before_filter, :
|
179
|
+
controller.send :before_filter, :_parse_soap_parameters, :except => [
|
180
|
+
:_generate_wsdl, :_invalid_action ]
|
181
|
+
controller.send :before_filter, :_authenticate_wsse, :except => [
|
182
|
+
:_generate_wsdl, :_invalid_action ]
|
183
|
+
controller.send :before_filter, :_map_soap_parameters, :except => [
|
184
|
+
:_generate_wsdl, :_invalid_action ]
|
179
185
|
controller.send :skip_before_filter, :verify_authenticity_token
|
180
186
|
end
|
181
187
|
|
data/lib/wash_out/engine.rb
CHANGED
@@ -1,49 +1,9 @@
|
|
1
|
+
|
1
2
|
module WashOut
|
2
3
|
class Engine < ::Rails::Engine
|
3
|
-
class << self
|
4
|
-
attr_accessor :parser
|
5
|
-
attr_accessor :namespace
|
6
|
-
attr_accessor :style
|
7
|
-
attr_accessor :snakecase, :camelize_output
|
8
|
-
attr_accessor :snakecase_input, :camelize_wsdl
|
9
|
-
attr_accessor :wsse_username, :wsse_password
|
10
|
-
attr_accessor :catch_xml_errors
|
11
|
-
end
|
12
|
-
|
13
|
-
self.parser = :rexml
|
14
|
-
|
15
|
-
self.namespace = 'urn:WashOut'
|
16
|
-
self.style = 'rpc'
|
17
|
-
self.snakecase = nil
|
18
|
-
|
19
|
-
self.snakecase_input = false
|
20
|
-
self.camelize_wsdl = false
|
21
|
-
|
22
|
-
self.wsse_username = nil
|
23
|
-
self.wsse_password = nil
|
24
|
-
|
25
4
|
config.wash_out = ActiveSupport::OrderedOptions.new
|
26
|
-
|
27
5
|
initializer "wash_out.configuration" do |app|
|
28
|
-
app.config.wash_out
|
29
|
-
self.class.send "#{key}=", value
|
30
|
-
end
|
31
|
-
|
32
|
-
app.config.wash_out.catch_xml_errors ||= false
|
33
|
-
|
34
|
-
unless self.class.snakecase.nil?
|
35
|
-
raise "Usage of wash_out.snakecase is deprecated. You should use wash_out.snakecase_input and wash_out.camelize_wsdl"
|
36
|
-
end
|
37
|
-
|
38
|
-
unless self.class.camelize_output.nil?
|
39
|
-
raise "Usage of wash_out.camelize_output is deprecated. You should use wash_out.camelize_wsdl option instead"
|
40
|
-
end
|
41
|
-
|
42
|
-
unless ['rpc','document'].include? self.class.style
|
43
|
-
raise "Invalid binding. Style must be one of #{['rpc','document'].join(',')}"
|
44
|
-
end
|
45
|
-
|
46
|
-
if self.class.catch_xml_errors
|
6
|
+
if app.config.wash_out[:catch_xml_errors]
|
47
7
|
app.config.middleware.insert_after 'ActionDispatch::ShowExceptions', WashOut::Middleware
|
48
8
|
end
|
49
9
|
end
|
data/lib/wash_out/param.rb
CHANGED
@@ -10,17 +10,17 @@ module WashOut
|
|
10
10
|
|
11
11
|
# Defines a WSDL parameter with name +name+ and type specifier +type+.
|
12
12
|
# The type specifier format is described in #parse_def.
|
13
|
-
def initialize(name, type, multiplied = false)
|
13
|
+
def initialize(soap_config, name, type, multiplied = false)
|
14
14
|
type ||= {}
|
15
|
-
|
15
|
+
@soap_config = soap_config
|
16
16
|
@name = name.to_s
|
17
17
|
@raw_name = name.to_s
|
18
18
|
@map = {}
|
19
19
|
@multiplied = multiplied
|
20
20
|
|
21
|
-
if
|
21
|
+
if soap_config.camelize_wsdl.to_s == 'lower'
|
22
22
|
@name = @name.camelize(:lower)
|
23
|
-
elsif
|
23
|
+
elsif soap_config.camelize_wsdl
|
24
24
|
@name = @name.camelize
|
25
25
|
end
|
26
26
|
|
@@ -28,11 +28,11 @@ module WashOut
|
|
28
28
|
@type = type.to_s
|
29
29
|
elsif type.is_a?(Class)
|
30
30
|
@type = 'struct'
|
31
|
-
@map = self.class.parse_def(type.wash_out_param_map)
|
31
|
+
@map = self.class.parse_def(soap_config, type.wash_out_param_map)
|
32
32
|
@source_class = type
|
33
33
|
else
|
34
34
|
@type = 'struct'
|
35
|
-
@map = self.class.parse_def(type)
|
35
|
+
@map = self.class.parse_def(soap_config, type)
|
36
36
|
end
|
37
37
|
end
|
38
38
|
|
@@ -50,13 +50,13 @@ module WashOut
|
|
50
50
|
data ||= {}
|
51
51
|
if @multiplied
|
52
52
|
data.map do |x|
|
53
|
-
map_struct x do |param,
|
54
|
-
param.load(
|
53
|
+
map_struct x do |param, dat, elem|
|
54
|
+
param.load(dat, elem)
|
55
55
|
end
|
56
56
|
end
|
57
57
|
else
|
58
|
-
map_struct data do |param,
|
59
|
-
param.load(
|
58
|
+
map_struct data do |param, dat, elem|
|
59
|
+
param.load(dat, elem)
|
60
60
|
end
|
61
61
|
end
|
62
62
|
else
|
@@ -64,7 +64,7 @@ module WashOut
|
|
64
64
|
when 'string'; :to_s
|
65
65
|
when 'integer'; :to_i
|
66
66
|
when 'double'; :to_f
|
67
|
-
when 'boolean'; lambda{|
|
67
|
+
when 'boolean'; lambda{|dat| dat === "0" ? false : !!dat}
|
68
68
|
when 'date'; :to_date
|
69
69
|
when 'datetime'; :to_datetime
|
70
70
|
when 'time'; :to_time
|
@@ -99,7 +99,7 @@ module WashOut
|
|
99
99
|
|
100
100
|
def basic_type
|
101
101
|
return name unless classified?
|
102
|
-
return source_class.wash_out_param_name
|
102
|
+
return source_class.wash_out_param_name(@soap_config)
|
103
103
|
end
|
104
104
|
|
105
105
|
def xsd_type
|
@@ -129,7 +129,7 @@ module WashOut
|
|
129
129
|
# +:parameter_name+ is ignored.
|
130
130
|
#
|
131
131
|
# This function returns an array of WashOut::Param objects.
|
132
|
-
def self.parse_def(definition)
|
132
|
+
def self.parse_def(soap_config, definition)
|
133
133
|
raise RuntimeError, "[] should not be used in your params. Use nil if you want to mark empty set." if definition == []
|
134
134
|
return [] if definition == nil
|
135
135
|
|
@@ -146,9 +146,9 @@ module WashOut
|
|
146
146
|
if opt.is_a? WashOut::Param
|
147
147
|
opt
|
148
148
|
elsif opt.is_a? Array
|
149
|
-
WashOut::Param.new(name, opt[0], true)
|
149
|
+
WashOut::Param.new(soap_config, name, opt[0], true)
|
150
150
|
else
|
151
|
-
WashOut::Param.new(name, opt)
|
151
|
+
WashOut::Param.new(soap_config, name, opt)
|
152
152
|
end
|
153
153
|
end
|
154
154
|
else
|
@@ -157,7 +157,7 @@ module WashOut
|
|
157
157
|
end
|
158
158
|
|
159
159
|
def flat_copy
|
160
|
-
copy = self.class.new(@name, @type.to_sym, @multiplied)
|
160
|
+
copy = self.class.new(@soap_config, @name, @type.to_sym, @multiplied)
|
161
161
|
copy.raw_name = raw_name
|
162
162
|
copy
|
163
163
|
end
|
data/lib/wash_out/router.rb
CHANGED
@@ -13,8 +13,8 @@ module WashOut
|
|
13
13
|
# RUBY18 1.8 does not have force_encoding.
|
14
14
|
soap_action.force_encoding('UTF-8') if soap_action.respond_to? :force_encoding
|
15
15
|
|
16
|
-
if
|
17
|
-
namespace = Regexp.escape
|
16
|
+
if controller.soap_config.namespace
|
17
|
+
namespace = Regexp.escape controller.soap_config.namespace.to_s
|
18
18
|
soap_action.gsub!(/^\"(#{namespace}(\/|#)?)?(.*)\"$/, '\3')
|
19
19
|
else
|
20
20
|
soap_action = soap_action[1...-1]
|
data/lib/wash_out/soap.rb
CHANGED
@@ -15,21 +15,22 @@ module WashOut
|
|
15
15
|
# which are not valid Ruby function names.
|
16
16
|
def soap_action(action, options={})
|
17
17
|
if action.is_a?(Symbol)
|
18
|
-
if
|
18
|
+
if soap_config.camelize_wsdl.to_s == 'lower'
|
19
19
|
options[:to] ||= action.to_s
|
20
20
|
action = action.to_s.camelize(:lower)
|
21
|
-
elsif
|
21
|
+
elsif soap_config.camelize_wsdl
|
22
22
|
options[:to] ||= action.to_s
|
23
23
|
action = action.to_s.camelize
|
24
24
|
end
|
25
|
+
|
25
26
|
end
|
26
27
|
|
27
|
-
default_response_tag =
|
28
|
+
default_response_tag = soap_config.camelize_wsdl ? 'Response' : '_response'
|
28
29
|
default_response_tag = "tns:#{action}#{default_response_tag}"
|
29
30
|
|
30
31
|
self.soap_actions[action] = {
|
31
|
-
:in => WashOut::Param.parse_def(options[:args]),
|
32
|
-
:out => WashOut::Param.parse_def(options[:return]),
|
32
|
+
:in => WashOut::Param.parse_def(soap_config, options[:args]),
|
33
|
+
:out => WashOut::Param.parse_def(soap_config, options[:return]),
|
33
34
|
:to => options[:to] || action,
|
34
35
|
:response_tag => options[:response_tag] || default_response_tag
|
35
36
|
}
|
@@ -37,6 +38,7 @@ module WashOut
|
|
37
38
|
end
|
38
39
|
|
39
40
|
included do
|
41
|
+
include WashOut::Configurable
|
40
42
|
include WashOut::Dispatcher
|
41
43
|
self.soap_actions = {}
|
42
44
|
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module WashOut
|
2
|
+
require 'forwardable'
|
3
|
+
# Configuration options for {Client}, defaulting to values
|
4
|
+
# in {Default}
|
5
|
+
class SoapConfig
|
6
|
+
extend Forwardable
|
7
|
+
DEFAULT_CONFIG = {
|
8
|
+
parser: :rexml,
|
9
|
+
namespace: 'urn:WashOut',
|
10
|
+
wsdl_style: 'rpc',
|
11
|
+
snakecase_input: false,
|
12
|
+
camelize_wsdl: false,
|
13
|
+
catch_xml_errors: false,
|
14
|
+
wsse_username: nil,
|
15
|
+
wsse_password: nil,
|
16
|
+
}
|
17
|
+
|
18
|
+
attr_reader :config
|
19
|
+
def_delegators :@config, :[], :[]=, :sort
|
20
|
+
|
21
|
+
|
22
|
+
# The keys allowed
|
23
|
+
def self.keys
|
24
|
+
@keys ||= config.keys
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.config
|
28
|
+
DEFAULT_CONFIG
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.soap_accessor(*syms)
|
32
|
+
syms.each do |sym|
|
33
|
+
|
34
|
+
unless sym =~ /^[_A-Za-z]\w*$/
|
35
|
+
raise NameError.new("invalid class attribute name: #{sym}")
|
36
|
+
end
|
37
|
+
class_eval(<<-EOS, __FILE__, __LINE__ + 1)
|
38
|
+
unless defined? @#{sym}
|
39
|
+
@#{sym} = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def #{sym}
|
43
|
+
@#{sym}
|
44
|
+
end
|
45
|
+
|
46
|
+
def #{sym}=(obj)
|
47
|
+
@#{sym} = obj
|
48
|
+
end
|
49
|
+
EOS
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
soap_accessor(*WashOut::SoapConfig.keys)
|
54
|
+
|
55
|
+
def initialize(options = {})
|
56
|
+
@config = {}
|
57
|
+
options.reverse_merge!(engine_config) if engine_config
|
58
|
+
options.reverse_merge!(DEFAULT_CONFIG)
|
59
|
+
configure options
|
60
|
+
end
|
61
|
+
|
62
|
+
def default?
|
63
|
+
DEFAULT_CONFIG.sort == config.sort
|
64
|
+
end
|
65
|
+
|
66
|
+
def configure(options = {})
|
67
|
+
@config.merge! validate_config!(options)
|
68
|
+
|
69
|
+
config.each do |key,value|
|
70
|
+
send("#{key}=", value)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def engine_config
|
77
|
+
@engine_config ||= WashOut::Engine.config.wash_out
|
78
|
+
end
|
79
|
+
|
80
|
+
def validate_config!(options = {})
|
81
|
+
rejected_keys = options.keys.reject do |key|
|
82
|
+
WashOut::SoapConfig.keys.include?(key)
|
83
|
+
end
|
84
|
+
|
85
|
+
if rejected_keys.any?
|
86
|
+
raise "The following keys are not allows: #{rejected_keys}\n Did you intend for one of the following? #{WashOut::SoapConfig.keys}"
|
87
|
+
end
|
88
|
+
options
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/wash_out/type.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module WashOut
|
2
2
|
class Type
|
3
|
+
|
3
4
|
def self.type_name(value)
|
4
5
|
@param_type_name = value
|
5
6
|
end
|
@@ -13,15 +14,15 @@ module WashOut
|
|
13
14
|
@param_map
|
14
15
|
end
|
15
16
|
|
16
|
-
def self.wash_out_param_name
|
17
|
+
def self.wash_out_param_name(soap_config = nil)
|
18
|
+
soap_config ||= WashOut::SoapConfig.new({})
|
17
19
|
@param_type_name ||= name.underscore.gsub '/', '.'
|
18
20
|
|
19
|
-
if
|
21
|
+
if soap_config.camelize_wsdl.to_s == 'lower'
|
20
22
|
@param_type_name = @param_type_name.camelize(:lower)
|
21
|
-
elsif
|
23
|
+
elsif soap_config.camelize_wsdl
|
22
24
|
@param_type_name = @param_type_name.camelize
|
23
25
|
end
|
24
|
-
|
25
26
|
@param_type_name
|
26
27
|
end
|
27
28
|
end
|
data/lib/wash_out/version.rb
CHANGED
data/lib/wash_out/wsse.rb
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
module WashOut
|
2
2
|
class Wsse
|
3
|
-
|
4
|
-
def self.authenticate(token)
|
5
|
-
wsse = self.new(token)
|
3
|
+
attr_reader :soap_config
|
4
|
+
def self.authenticate(soap_config, token)
|
5
|
+
wsse = self.new(soap_config, token)
|
6
6
|
|
7
7
|
unless wsse.eligible?
|
8
8
|
raise WashOut::Dispatcher::SOAPError, "Unauthorized"
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
def initialize(token)
|
12
|
+
def initialize(soap_config, token)
|
13
|
+
@soap_config = soap_config
|
13
14
|
if token.blank? && required?
|
14
15
|
raise WashOut::Dispatcher::SOAPError, "Missing required UsernameToken"
|
15
16
|
end
|
@@ -17,15 +18,15 @@ module WashOut
|
|
17
18
|
end
|
18
19
|
|
19
20
|
def required?
|
20
|
-
!
|
21
|
+
!soap_config.wsse_username.blank?
|
21
22
|
end
|
22
23
|
|
23
24
|
def expected_user
|
24
|
-
|
25
|
+
soap_config.wsse_username
|
25
26
|
end
|
26
27
|
|
27
28
|
def expected_password
|
28
|
-
|
29
|
+
soap_config.wsse_password
|
29
30
|
end
|
30
31
|
|
31
32
|
def matches_expected_digest?(password)
|
data/lib/wash_out.rb
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
require 'wash_out/configurable'
|
2
|
+
require 'wash_out/soap_config'
|
3
|
+
require 'wash_out/soap'
|
1
4
|
require 'wash_out/engine'
|
2
5
|
require 'wash_out/param'
|
3
6
|
require 'wash_out/dispatcher'
|
@@ -28,9 +31,17 @@ ActionController::Renderers.add :soap do |what, options|
|
|
28
31
|
_render_soap(what, options)
|
29
32
|
end
|
30
33
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
34
|
+
ActionController::Base.class_eval do
|
35
|
+
|
36
|
+
# Define a SOAP service. The function has no required +options+:
|
37
|
+
# but allow any of :parser, :namespace, :wsdl_style, :snakecase_input,
|
38
|
+
# :camelize_wsdl, :wsse_username, :wsse_password and :catch_xml_errors.
|
39
|
+
#
|
40
|
+
# Any of the the params provided allows for overriding the defaults
|
41
|
+
# (like supporting multiple namespaces instead of application wide such)
|
42
|
+
#
|
43
|
+
def self.soap_service(options={})
|
44
|
+
include WashOut::SOAP
|
45
|
+
self.soap_config = options
|
35
46
|
end
|
36
|
-
end
|
47
|
+
end
|
@@ -5,7 +5,7 @@ require 'spec_helper'
|
|
5
5
|
describe WashOut::Dispatcher do
|
6
6
|
|
7
7
|
class Dispatcher < ApplicationController
|
8
|
-
|
8
|
+
soap_service
|
9
9
|
|
10
10
|
def self.mock(text="")
|
11
11
|
dispatcher = self.new
|
@@ -60,27 +60,27 @@ describe WashOut::Dispatcher do
|
|
60
60
|
|
61
61
|
describe "#_load_params" do
|
62
62
|
let(:dispatcher) { Dispatcher.new }
|
63
|
-
|
63
|
+
let(:soap_config) { WashOut::SoapConfig.new({ camelize_wsdl: false }) }
|
64
64
|
it "should load params for an array" do
|
65
|
-
spec = WashOut::Param.parse_def( {:my_array => [:integer] } )
|
65
|
+
spec = WashOut::Param.parse_def(soap_config, {:my_array => [:integer] } )
|
66
66
|
xml_data = {:my_array => [1, 2, 3]}
|
67
67
|
dispatcher._load_params(spec, xml_data).should == {"my_array" => [1, 2, 3]}
|
68
68
|
end
|
69
69
|
|
70
70
|
it "should load params for an empty array" do
|
71
|
-
spec = WashOut::Param.parse_def( {:my_array => [:integer] } )
|
71
|
+
spec = WashOut::Param.parse_def(soap_config, {:my_array => [:integer] } )
|
72
72
|
xml_data = {}
|
73
73
|
dispatcher._load_params(spec, xml_data).should == {}
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should load params for a nested array" do
|
77
|
-
spec = WashOut::Param.parse_def( {:nested => {:my_array => [:integer]}} )
|
77
|
+
spec = WashOut::Param.parse_def(soap_config, {:nested => {:my_array => [:integer]}} )
|
78
78
|
xml_data = {:nested => {:my_array => [1, 2, 3]}}
|
79
79
|
dispatcher._load_params(spec, xml_data).should == {"nested" => {"my_array" => [1, 2, 3]}}
|
80
80
|
end
|
81
81
|
|
82
82
|
it "should load params for an empty nested array" do
|
83
|
-
spec = WashOut::Param.parse_def( {:nested => {:empty => [:integer] }} )
|
83
|
+
spec = WashOut::Param.parse_def(soap_config, {:nested => {:empty => [:integer] }} )
|
84
84
|
xml_data = {:nested => nil}
|
85
85
|
dispatcher._load_params(spec, xml_data).should == {"nested" => {}}
|
86
86
|
end
|
@@ -5,18 +5,21 @@ require 'spec_helper'
|
|
5
5
|
describe WashOut::Param do
|
6
6
|
|
7
7
|
context "custom types" do
|
8
|
+
|
8
9
|
class Abraka1 < WashOut::Type
|
9
10
|
map(
|
10
11
|
:test => :string
|
11
12
|
)
|
12
13
|
end
|
14
|
+
|
13
15
|
class Abraka2 < WashOut::Type
|
14
16
|
type_name 'test'
|
15
17
|
map :foo => Abraka1
|
16
18
|
end
|
17
19
|
|
18
20
|
it "loads custom_types" do
|
19
|
-
|
21
|
+
soap_config = WashOut::SoapConfig.new({ camelize_wsdl: false })
|
22
|
+
map = WashOut::Param.parse_def soap_config, Abraka2
|
20
23
|
|
21
24
|
map.should be_a_kind_of(Array)
|
22
25
|
map[0].name.should == 'foo'
|
@@ -24,9 +27,9 @@ describe WashOut::Param do
|
|
24
27
|
end
|
25
28
|
|
26
29
|
it "respects camelization setting" do
|
27
|
-
WashOut::
|
30
|
+
soap_config = WashOut::SoapConfig.new({ camelize_wsdl: true })
|
28
31
|
|
29
|
-
map = WashOut::Param.parse_def Abraka2
|
32
|
+
map = WashOut::Param.parse_def soap_config, Abraka2
|
30
33
|
|
31
34
|
map.should be_a_kind_of(Array)
|
32
35
|
map[0].name.should == 'Foo'
|
@@ -35,14 +38,16 @@ describe WashOut::Param do
|
|
35
38
|
end
|
36
39
|
|
37
40
|
it "should accept nested empty arrays" do
|
38
|
-
|
41
|
+
soap_config = WashOut::SoapConfig.new({ camelize_wsdl: false })
|
42
|
+
map = WashOut::Param.parse_def(soap_config, {:nested => {:some_attr => :string, :empty => [:integer] }} )
|
39
43
|
map[0].load( {:nested => nil}, :nested).should == {}
|
40
44
|
end
|
41
45
|
|
42
46
|
describe "booleans" do
|
47
|
+
let(:soap_config) { WashOut::SoapConfig.new({ camelize_wsdl: false }) }
|
43
48
|
# following http://www.w3.org/TR/xmlschema-2/#boolean, only true, false, 0 and 1 are allowed.
|
44
49
|
# Nori maps the strings true and false to TrueClass and FalseClass, but not 0 and 1.
|
45
|
-
let(:map) { WashOut::Param.parse_def(:value => :boolean) }
|
50
|
+
let(:map) { WashOut::Param.parse_def(soap_config, :value => :boolean) }
|
46
51
|
|
47
52
|
it "should accept 'true' and '1'" do
|
48
53
|
map[0].load({:value => true}, :value).should be_true
|
data/spec/lib/wash_out_spec.rb
CHANGED
@@ -3,11 +3,6 @@
|
|
3
3
|
require 'spec_helper'
|
4
4
|
|
5
5
|
describe WashOut do
|
6
|
-
before :each do
|
7
|
-
WashOut::Engine.snakecase_input = true
|
8
|
-
WashOut::Engine.camelize_wsdl = true
|
9
|
-
WashOut::Engine.namespace = false
|
10
|
-
end
|
11
6
|
|
12
7
|
let :nori do
|
13
8
|
Nori.new(
|
@@ -54,11 +49,12 @@ describe WashOut do
|
|
54
49
|
mock_controller do
|
55
50
|
soap_action :result, :args => nil, :return => :int
|
56
51
|
|
57
|
-
soap_action "getArea", :args
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
52
|
+
soap_action "getArea", :args => {
|
53
|
+
:circle => [{
|
54
|
+
:center => { :x => [:integer], :y => :integer },
|
55
|
+
:radius => :double
|
56
|
+
}]},
|
57
|
+
:return => { :area => :double }
|
62
58
|
soap_action "rocky", :args => { :circle1 => { :x => :integer } },
|
63
59
|
:return => { :circle2 => { :y => :integer } }
|
64
60
|
end
|
@@ -429,7 +425,7 @@ describe WashOut do
|
|
429
425
|
context "errors" do
|
430
426
|
it "raise for incorrect requests" do
|
431
427
|
mock_controller do
|
432
|
-
soap_action "duty",
|
428
|
+
soap_action "duty",
|
433
429
|
:args => {:bad => {:a => :string, :b => :string}, :good => {:a => :string, :b => :string}},
|
434
430
|
:return => nil
|
435
431
|
def duty
|
@@ -564,10 +560,7 @@ describe WashOut do
|
|
564
560
|
end
|
565
561
|
|
566
562
|
it "handles snakecase option properly" do
|
567
|
-
|
568
|
-
WashOut::Engine.camelize_wsdl = false
|
569
|
-
|
570
|
-
mock_controller do
|
563
|
+
mock_controller(snakecase_input: false, camelize_wsdl: false) do
|
571
564
|
soap_action "rocknroll", :args => {:ZOMG => :string}, :return => nil
|
572
565
|
def rocknroll
|
573
566
|
params["ZOMG"].should == "yam!"
|
@@ -583,10 +576,7 @@ describe WashOut do
|
|
583
576
|
describe "WS Security" do
|
584
577
|
|
585
578
|
it "appends username_token to params" do
|
586
|
-
|
587
|
-
WashOut::Engine.wsse_password = nil
|
588
|
-
|
589
|
-
mock_controller do
|
579
|
+
mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
|
590
580
|
soap_action "checkToken", :args => :integer, :return => nil, :to => 'check_token'
|
591
581
|
def check_token
|
592
582
|
request.env['WSSE_TOKEN']['username'].should == "gorilla"
|
@@ -601,10 +591,7 @@ describe WashOut do
|
|
601
591
|
end
|
602
592
|
|
603
593
|
it "handles PasswordText auth" do
|
604
|
-
|
605
|
-
WashOut::Engine.wsse_password = "secret"
|
606
|
-
|
607
|
-
mock_controller do
|
594
|
+
mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
|
608
595
|
soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
|
609
596
|
def check_auth
|
610
597
|
render :soap => (params[:value] == 42)
|
@@ -629,10 +616,7 @@ describe WashOut do
|
|
629
616
|
end
|
630
617
|
|
631
618
|
it "handles PasswordDigest auth" do
|
632
|
-
|
633
|
-
WashOut::Engine.wsse_password = "secret"
|
634
|
-
|
635
|
-
mock_controller do
|
619
|
+
mock_controller(wsse_username: "gorilla", wsse_password: "secret") do
|
636
620
|
soap_action "checkAuth", :args => :integer, :return => :boolean, :to => 'check_auth'
|
637
621
|
def check_auth
|
638
622
|
render :soap => (params[:value] == 42)
|
data/spec/spec_helper.rb
CHANGED
@@ -27,9 +27,11 @@ RSpec.configure do |config|
|
|
27
27
|
|
28
28
|
config.mock_with :rspec
|
29
29
|
config.before(:all) do
|
30
|
-
WashOut::Engine.
|
31
|
-
|
32
|
-
|
30
|
+
WashOut::Engine.config.wash_out = {
|
31
|
+
snakecase_input: false,
|
32
|
+
camelize_wsdl: false,
|
33
|
+
namespace: false
|
34
|
+
}
|
33
35
|
end
|
34
36
|
|
35
37
|
config.after(:suite) do
|
@@ -51,11 +53,14 @@ Dummy::Application.routes.draw do
|
|
51
53
|
wash_out :api
|
52
54
|
end
|
53
55
|
|
54
|
-
def mock_controller(&block)
|
56
|
+
def mock_controller(options = {}, &block)
|
55
57
|
Object.send :remove_const, :ApiController if defined?(ApiController)
|
56
58
|
Object.send :const_set, :ApiController, Class.new(ApplicationController) {
|
57
|
-
|
58
|
-
|
59
|
+
soap_service options.reverse_merge({
|
60
|
+
snakecase_input: true,
|
61
|
+
camelize_wsdl: true,
|
62
|
+
namespace: false
|
63
|
+
})
|
59
64
|
class_exec &block if block
|
60
65
|
}
|
61
66
|
|
data/wash_out.gemspec
CHANGED
@@ -12,6 +12,9 @@ Gem::Specification.new do |s|
|
|
12
12
|
|
13
13
|
s.files = `git ls-files`.split("\n")
|
14
14
|
s.require_paths = ["lib"]
|
15
|
-
|
15
|
+
s.post_install_message = <<-EOS
|
16
|
+
Please replace `include WashOut::SOAP` with `soap_service`
|
17
|
+
in your controllers if you are upgrading from a version before 0.8.5.
|
18
|
+
EOS
|
16
19
|
s.add_dependency("nori", ">= 2.0.0")
|
17
20
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wash_out
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0.beta.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Boris Staal
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-09-
|
12
|
+
date: 2013-09-08 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: nori
|
@@ -50,6 +50,7 @@ files:
|
|
50
50
|
- app/views/wash_with_soap/rpc/wsdl.builder
|
51
51
|
- init.rb
|
52
52
|
- lib/wash_out.rb
|
53
|
+
- lib/wash_out/configurable.rb
|
53
54
|
- lib/wash_out/dispatcher.rb
|
54
55
|
- lib/wash_out/engine.rb
|
55
56
|
- lib/wash_out/middleware.rb
|
@@ -57,6 +58,7 @@ files:
|
|
57
58
|
- lib/wash_out/param.rb
|
58
59
|
- lib/wash_out/router.rb
|
59
60
|
- lib/wash_out/soap.rb
|
61
|
+
- lib/wash_out/soap_config.rb
|
60
62
|
- lib/wash_out/type.rb
|
61
63
|
- lib/wash_out/version.rb
|
62
64
|
- lib/wash_out/wsse.rb
|
@@ -93,7 +95,9 @@ files:
|
|
93
95
|
homepage: http://github.com/inossidabile/wash_out/
|
94
96
|
licenses: []
|
95
97
|
metadata: {}
|
96
|
-
post_install_message:
|
98
|
+
post_install_message: |2
|
99
|
+
Please replace `include WashOut::SOAP` with `soap_service`
|
100
|
+
in your controllers if you are upgrading from a version before 0.8.5.
|
97
101
|
rdoc_options: []
|
98
102
|
require_paths:
|
99
103
|
- lib
|
@@ -104,9 +108,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
104
108
|
version: '0'
|
105
109
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
106
110
|
requirements:
|
107
|
-
- - '
|
111
|
+
- - '>'
|
108
112
|
- !ruby/object:Gem::Version
|
109
|
-
version:
|
113
|
+
version: 1.3.1
|
110
114
|
requirements: []
|
111
115
|
rubyforge_project:
|
112
116
|
rubygems_version: 2.0.6
|