wash-out 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +1 -0
  4. data/.travis.yml +35 -0
  5. data/Appraisals +25 -0
  6. data/CHANGELOG.md +102 -0
  7. data/Gemfile +16 -0
  8. data/Guardfile +12 -0
  9. data/LICENSE +22 -0
  10. data/README.md +246 -0
  11. data/Rakefile +13 -0
  12. data/app/helpers/wash_out_helper.rb +106 -0
  13. data/app/views/wash_out/document/error.builder +9 -0
  14. data/app/views/wash_out/document/response.builder +10 -0
  15. data/app/views/wash_out/document/wsdl.builder +68 -0
  16. data/app/views/wash_out/rpc/error.builder +10 -0
  17. data/app/views/wash_out/rpc/response.builder +11 -0
  18. data/app/views/wash_out/rpc/wsdl.builder +68 -0
  19. data/gemfiles/rails_3.1.3.gemfile +20 -0
  20. data/gemfiles/rails_3.2.12.gemfile +20 -0
  21. data/gemfiles/rails_4.0.0.gemfile +19 -0
  22. data/gemfiles/rails_4.1.0.gemfile +19 -0
  23. data/gemfiles/rails_4.2.0.gemfile +19 -0
  24. data/gemfiles/rails_5.0.0.beta2.gemfile +19 -0
  25. data/init.rb +1 -0
  26. data/lib/wash_out.rb +53 -0
  27. data/lib/wash_out/configurable.rb +41 -0
  28. data/lib/wash_out/dispatcher.rb +218 -0
  29. data/lib/wash_out/engine.rb +12 -0
  30. data/lib/wash_out/middleware.rb +41 -0
  31. data/lib/wash_out/model.rb +29 -0
  32. data/lib/wash_out/param.rb +200 -0
  33. data/lib/wash_out/router.rb +95 -0
  34. data/lib/wash_out/soap.rb +48 -0
  35. data/lib/wash_out/soap_config.rb +93 -0
  36. data/lib/wash_out/type.rb +29 -0
  37. data/lib/wash_out/version.rb +3 -0
  38. data/lib/wash_out/wsse.rb +101 -0
  39. data/spec/dummy/Rakefile +7 -0
  40. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  41. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  42. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  43. data/spec/dummy/config.ru +4 -0
  44. data/spec/dummy/config/application.rb +51 -0
  45. data/spec/dummy/config/boot.rb +10 -0
  46. data/spec/dummy/config/environment.rb +5 -0
  47. data/spec/dummy/config/environments/development.rb +23 -0
  48. data/spec/dummy/config/environments/test.rb +30 -0
  49. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  50. data/spec/dummy/config/initializers/inflections.rb +10 -0
  51. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  52. data/spec/dummy/config/initializers/secret_token.rb +8 -0
  53. data/spec/dummy/config/initializers/session_store.rb +8 -0
  54. data/spec/dummy/config/locales/en.yml +5 -0
  55. data/spec/dummy/config/routes.rb +58 -0
  56. data/spec/dummy/public/404.html +26 -0
  57. data/spec/dummy/public/422.html +26 -0
  58. data/spec/dummy/public/500.html +26 -0
  59. data/spec/dummy/public/favicon.ico +0 -0
  60. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  61. data/spec/dummy/script/rails +6 -0
  62. data/spec/lib/wash_out/dispatcher_spec.rb +99 -0
  63. data/spec/lib/wash_out/middleware_spec.rb +33 -0
  64. data/spec/lib/wash_out/param_spec.rb +94 -0
  65. data/spec/lib/wash_out/router_spec.rb +22 -0
  66. data/spec/lib/wash_out/type_spec.rb +41 -0
  67. data/spec/lib/wash_out_spec.rb +754 -0
  68. data/spec/spec_helper.rb +82 -0
  69. data/wash_out.gemspec +21 -0
  70. metadata +128 -0
@@ -0,0 +1,13 @@
1
+ require 'bundler/setup'
2
+ require 'bundler/gem_tasks'
3
+ require 'appraisal'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ task :console do
9
+ require "action_controller/railtie"
10
+ require "rails/test_unit/railtie"
11
+ Bundler.require
12
+ binding.pry
13
+ end
@@ -0,0 +1,106 @@
1
+ module WashOutHelper
2
+
3
+ def wsdl_data_options(param)
4
+ case controller.soap_config.wsdl_style
5
+ when 'rpc'
6
+ { :"xsi:type" => param.namespaced_type }
7
+ when 'document'
8
+ { }
9
+ end
10
+ end
11
+
12
+ def wsdl_data_attrs(param)
13
+ param.map.reduce({}) do |memo, p|
14
+ if p.respond_to?(:attribute?) && p.attribute?
15
+ memo.merge p.attr_name => p.value
16
+ else
17
+ memo
18
+ end
19
+ end
20
+ end
21
+
22
+ def wsdl_data(xml, params)
23
+ params.each do |param|
24
+ next if param.attribute?
25
+
26
+ tag_name = param.name
27
+ param_options = wsdl_data_options(param)
28
+ param_options.merge! wsdl_data_attrs(param)
29
+
30
+ if param.struct?
31
+ if param.multiplied
32
+ param.map.each do |p|
33
+ attrs = wsdl_data_attrs p
34
+ if p.is_a?(Array) || p.map.size > attrs.size
35
+ blk = proc { wsdl_data(xml, p.map) }
36
+ end
37
+ attrs.reject! { |_, v| v.nil? }
38
+ xml.tag! tag_name, param_options.merge(attrs), &blk
39
+ end
40
+ else
41
+ xml.tag! tag_name, param_options do
42
+ wsdl_data(xml, param.map)
43
+ end
44
+ end
45
+ else
46
+ if param.multiplied
47
+ param.value = [] unless param.value.is_a?(Array)
48
+ param.value.each do |v|
49
+ xml.tag! tag_name, v, param_options
50
+ end
51
+ else
52
+ xml.tag! tag_name, param.value, param_options
53
+ end
54
+ end
55
+ end
56
+ end
57
+
58
+ def wsdl_type(xml, param, defined=[])
59
+ more = []
60
+
61
+ if param.struct?
62
+ if !defined.include?(param.basic_type)
63
+ xml.tag! "xsd:complexType", :name => param.basic_type do
64
+ attrs, elems = [], []
65
+ param.map.each do |value|
66
+ more << value if value.struct?
67
+ if value.attribute?
68
+ attrs << value
69
+ else
70
+ elems << value
71
+ end
72
+ end
73
+
74
+ if elems.any?
75
+ xml.tag! "xsd:sequence" do
76
+ elems.each do |value|
77
+ xml.tag! "xsd:element", wsdl_occurence(value, false, :name => value.name, :type => value.namespaced_type)
78
+ end
79
+ end
80
+ end
81
+
82
+ attrs.each do |value|
83
+ xml.tag! "xsd:attribute", wsdl_occurence(value, false, :name => value.attr_name, :type => value.namespaced_type)
84
+ end
85
+ end
86
+
87
+ defined << param.basic_type
88
+ elsif !param.classified?
89
+ raise RuntimeError, "Duplicate use of `#{param.basic_type}` type name. Consider using classified types."
90
+ end
91
+ end
92
+
93
+ more.each do |p|
94
+ wsdl_type xml, p, defined
95
+ end
96
+ end
97
+
98
+ def wsdl_occurence(param, inject, extend_with = {})
99
+ data = !param.multiplied ? {} : {
100
+ "#{'xsi:' if inject}minOccurs" => 0,
101
+ "#{'xsi:' if inject}maxOccurs" => 'unbounded'
102
+ }
103
+
104
+ extend_with.merge(data)
105
+ end
106
+ end
@@ -0,0 +1,9 @@
1
+ xml.instruct!
2
+ xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envelope/' do
3
+ xml.tag! "soap:Body" do
4
+ xml.tag! "soap:Fault" do
5
+ xml.faultcode error_code
6
+ xml.faultstring error_message
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ xml.instruct!
2
+ xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envelope/',
3
+ "xmlns:xsd" => 'http://www.w3.org/2001/XMLSchema',
4
+ "xmlns:tns" => @namespace do
5
+ xml.tag! "soap:Body" do
6
+ xml.tag! "tns:#{@action_spec[:response_tag]}" do
7
+ wsdl_data xml, result
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,68 @@
1
+ xml.instruct!
2
+ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
3
+ 'xmlns:tns' => @namespace,
4
+ 'xmlns:soap' => 'http://schemas.xmlsoap.org/wsdl/soap/',
5
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
6
+ 'xmlns:soap-enc' => 'http://schemas.xmlsoap.org/soap/encoding/',
7
+ 'xmlns:wsdl' => 'http://schemas.xmlsoap.org/wsdl/',
8
+ 'name' => @name,
9
+ 'targetNamespace' => @namespace do
10
+
11
+ xml.types do
12
+ xml.tag! "schema", :targetNamespace => @namespace, :xmlns => 'http://www.w3.org/2001/XMLSchema' do
13
+ defined = []
14
+ @map.each do |operation, formats|
15
+ (formats[:in] + formats[:out]).each do |p|
16
+ wsdl_type xml, p, defined
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ @map.each do |operation, formats|
23
+ xml.message :name => "#{operation}" do
24
+ formats[:in].each do |p|
25
+ xml.part wsdl_occurence(p, false, :name => p.name, :type => p.namespaced_type)
26
+ end
27
+ end
28
+ xml.message :name => formats[:response_tag] do
29
+ formats[:out].each do |p|
30
+ xml.part wsdl_occurence(p, false, :name => p.name, :type => p.namespaced_type)
31
+ end
32
+ end
33
+ end
34
+
35
+ xml.portType :name => "#{@name}_port" do
36
+ @map.each do |operation, formats|
37
+ xml.operation :name => operation do
38
+ xml.input :message => "tns:#{operation}"
39
+ xml.output :message => "tns:#{formats[:response_tag]}"
40
+ end
41
+ end
42
+ end
43
+
44
+ xml.binding :name => "#{@name}_binding", :type => "tns:#{@name}_port" do
45
+ xml.tag! "soap:binding", :style => 'document', :transport => 'http://schemas.xmlsoap.org/soap/http'
46
+ @map.keys.each do |operation|
47
+ xml.operation :name => operation do
48
+ xml.tag! "soap:operation", :soapAction => operation
49
+ xml.input do
50
+ xml.tag! "soap:body",
51
+ :use => "literal",
52
+ :namespace => @namespace
53
+ end
54
+ xml.output do
55
+ xml.tag! "soap:body",
56
+ :use => "literal",
57
+ :namespace => @namespace
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ xml.service :name => "service" do
64
+ xml.port :name => "#{@name}_port", :binding => "tns:#{@name}_binding" do
65
+ xml.tag! "soap:address", :location => send("#{@name}_action_url")
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,10 @@
1
+ xml.instruct!
2
+ xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envelope/',
3
+ "xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance' do
4
+ xml.tag! "soap:Body" do
5
+ xml.tag! "soap:Fault", :encodingStyle => 'http://schemas.xmlsoap.org/soap/encoding/' do
6
+ xml.faultcode error_code, 'xsi:type' => 'xsd:QName'
7
+ xml.faultstring error_message, 'xsi:type' => 'xsd:string'
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ xml.instruct!
2
+ xml.tag! "soap:Envelope", "xmlns:soap" => 'http://schemas.xmlsoap.org/soap/envelope/',
3
+ "xmlns:xsd" => 'http://www.w3.org/2001/XMLSchema',
4
+ "xmlns:xsi" => 'http://www.w3.org/2001/XMLSchema-instance',
5
+ "xmlns:tns" => @namespace do
6
+ xml.tag! "soap:Body" do
7
+ xml.tag! "tns:#{@action_spec[:response_tag]}" do
8
+ wsdl_data xml, result
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,68 @@
1
+ xml.instruct!
2
+ xml.definitions 'xmlns' => 'http://schemas.xmlsoap.org/wsdl/',
3
+ 'xmlns:tns' => @namespace,
4
+ 'xmlns:soap' => 'http://schemas.xmlsoap.org/wsdl/soap/',
5
+ 'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
6
+ 'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
7
+ 'xmlns:soap-enc' => 'http://schemas.xmlsoap.org/soap/encoding/',
8
+ 'xmlns:wsdl' => 'http://schemas.xmlsoap.org/wsdl/',
9
+ 'name' => @name,
10
+ 'targetNamespace' => @namespace do
11
+ xml.types do
12
+ xml.tag! "schema", :targetNamespace => @namespace, :xmlns => 'http://www.w3.org/2001/XMLSchema' do
13
+ defined = []
14
+ @map.each do |operation, formats|
15
+ (formats[:in] + formats[:out]).each do |p|
16
+ wsdl_type xml, p, defined
17
+ end
18
+ end
19
+ end
20
+ end
21
+
22
+ @map.each do |operation, formats|
23
+ xml.message :name => "#{operation}" do
24
+ formats[:in].each do |p|
25
+ xml.part wsdl_occurence(p, true, :name => p.name, :type => p.namespaced_type)
26
+ end
27
+ end
28
+ xml.message :name => formats[:response_tag] do
29
+ formats[:out].each do |p|
30
+ xml.part wsdl_occurence(p, true, :name => p.name, :type => p.namespaced_type)
31
+ end
32
+ end
33
+ end
34
+
35
+ xml.portType :name => "#{@name}_port" do
36
+ @map.each do |operation, formats|
37
+ xml.operation :name => operation do
38
+ xml.input :message => "tns:#{operation}"
39
+ xml.output :message => "tns:#{formats[:response_tag]}"
40
+ end
41
+ end
42
+ end
43
+
44
+ xml.binding :name => "#{@name}_binding", :type => "tns:#{@name}_port" do
45
+ xml.tag! "soap:binding", :style => 'rpc', :transport => 'http://schemas.xmlsoap.org/soap/http'
46
+ @map.keys.each do |operation|
47
+ xml.operation :name => operation do
48
+ xml.tag! "soap:operation", :soapAction => operation
49
+ xml.input do
50
+ xml.tag! "soap:body",
51
+ :use => "encoded", :encodingStyle => 'http://schemas.xmlsoap.org/soap/encoding/',
52
+ :namespace => @namespace
53
+ end
54
+ xml.output do
55
+ xml.tag! "soap:body",
56
+ :use => "encoded", :encodingStyle => 'http://schemas.xmlsoap.org/soap/encoding/',
57
+ :namespace => @namespace
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ xml.service :name => "service" do
64
+ xml.port :name => "#{@name}_port", :binding => "tns:#{@name}_binding" do
65
+ xml.tag! "soap:address", :location => send("#{@name}_action_url")
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,20 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "wasabi"
6
+ gem "savon", ">= 2.0.0"
7
+ gem "httpi"
8
+ gem "rspec-rails"
9
+ gem "guard"
10
+ gem "guard-rspec"
11
+ gem "rb-fsevent"
12
+ gem "appraisal"
13
+ gem "tzinfo"
14
+ gem "pry"
15
+ gem "simplecov"
16
+ gem "simplecov-summary"
17
+ gem "rails", "3.1.3"
18
+ gem "test-unit"
19
+
20
+ gemspec :path => "../"
@@ -0,0 +1,20 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "wasabi"
6
+ gem "savon", ">= 2.0.0"
7
+ gem "httpi"
8
+ gem "rspec-rails"
9
+ gem "guard"
10
+ gem "guard-rspec"
11
+ gem "rb-fsevent"
12
+ gem "appraisal"
13
+ gem "tzinfo"
14
+ gem "pry"
15
+ gem "simplecov"
16
+ gem "simplecov-summary"
17
+ gem "rails", "3.2.12"
18
+ gem "test-unit"
19
+
20
+ gemspec :path => "../"
@@ -0,0 +1,19 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "wasabi"
6
+ gem "savon", ">= 2.0.0"
7
+ gem "httpi"
8
+ gem "rspec-rails"
9
+ gem "guard"
10
+ gem "guard-rspec"
11
+ gem "rb-fsevent"
12
+ gem "appraisal"
13
+ gem "tzinfo"
14
+ gem "pry"
15
+ gem "simplecov"
16
+ gem "simplecov-summary"
17
+ gem "rails", "4.0.0"
18
+
19
+ gemspec :path => "../"
@@ -0,0 +1,19 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "wasabi"
6
+ gem "savon", ">= 2.0.0"
7
+ gem "httpi"
8
+ gem "rspec-rails"
9
+ gem "guard"
10
+ gem "guard-rspec"
11
+ gem "rb-fsevent"
12
+ gem "appraisal"
13
+ gem "tzinfo"
14
+ gem "pry"
15
+ gem "simplecov"
16
+ gem "simplecov-summary"
17
+ gem "rails", "4.1.0"
18
+
19
+ gemspec :path => "../"
@@ -0,0 +1,19 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "wasabi"
6
+ gem "savon", ">= 2.0.0"
7
+ gem "httpi"
8
+ gem "rspec-rails"
9
+ gem "guard"
10
+ gem "guard-rspec"
11
+ gem "rb-fsevent"
12
+ gem "appraisal"
13
+ gem "tzinfo"
14
+ gem "pry"
15
+ gem "simplecov"
16
+ gem "simplecov-summary"
17
+ gem "rails", "4.2.0"
18
+
19
+ gemspec :path => "../"
@@ -0,0 +1,19 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "http://rubygems.org"
4
+
5
+ gem "wasabi"
6
+ gem "savon", ">= 2.0.0"
7
+ gem "httpi"
8
+ gem "rspec-rails"
9
+ gem "guard"
10
+ gem "guard-rspec"
11
+ gem "rb-fsevent"
12
+ gem "appraisal"
13
+ gem "tzinfo"
14
+ gem "pry"
15
+ gem "simplecov"
16
+ gem "simplecov-summary"
17
+ gem "rails", "5.0.0.beta2"
18
+
19
+ gemspec :path => "../"
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'wash_out'
@@ -0,0 +1,53 @@
1
+ require 'wash_out/configurable'
2
+ require 'wash_out/soap_config'
3
+ require 'wash_out/soap'
4
+ require 'wash_out/engine'
5
+ require 'wash_out/param'
6
+ require 'wash_out/dispatcher'
7
+ require 'wash_out/soap'
8
+ require 'wash_out/router'
9
+ require 'wash_out/type'
10
+ require 'wash_out/model'
11
+ require 'wash_out/wsse'
12
+ require 'wash_out/middleware'
13
+
14
+ module WashOut
15
+ def self.root
16
+ File.expand_path '../..', __FILE__
17
+ end
18
+ end
19
+
20
+ module ActionDispatch::Routing
21
+ class Mapper
22
+ # Adds the routes for a SOAP endpoint at +controller+.
23
+ def wash_out(controller_name, options={})
24
+ options.each_with_index { |key, value| @scope[key] = value } if @scope
25
+ controller_class_name = [options[:module], controller_name].compact.join("/")
26
+
27
+ match "#{controller_name}/wsdl" => "#{controller_name}#_generate_wsdl", :via => :get, :format => false
28
+ match "#{controller_name}/action" => WashOut::Router.new(controller_class_name), :via => [:get, :post], :defaults => { :controller => controller_class_name, :action => '_action' }, :format => false
29
+ end
30
+ end
31
+ end
32
+
33
+ Mime::Type.register "application/soap+xml", :soap
34
+ ActiveRecord::Base.send :extend, WashOut::Model if defined?(ActiveRecord)
35
+
36
+ ActionController::Renderers.add :soap do |what, options|
37
+ _render_soap(what, options)
38
+ end
39
+
40
+ ActionController::Base.class_eval do
41
+
42
+ # Define a SOAP service. The function has no required +options+:
43
+ # but allow any of :parser, :namespace, :wsdl_style, :snakecase_input,
44
+ # :camelize_wsdl, :wsse_username, :wsse_password and :catch_xml_errors.
45
+ #
46
+ # Any of the the params provided allows for overriding the defaults
47
+ # (like supporting multiple namespaces instead of application wide such)
48
+ #
49
+ def self.soap_service(options={})
50
+ include WashOut::SOAP
51
+ self.soap_config = options
52
+ end
53
+ end