soap4r-middleware 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in soap4r-middleware.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,61 @@
1
+ Soap4r Rack Middleware
2
+ ======================
3
+
4
+ This small library provides a Rack Middleware interface to exposing
5
+ Soap4r server endpoints. This is a lightweight alternative to using
6
+ ActionWebService for exposing SOAP in a Rails application, as well as
7
+ allowing SOAP endpoints in any other Rack-based application. It's been
8
+ tested with Rails 2.3.x, but should work fine in Rails 3 as well.
9
+
10
+ Install
11
+ -------
12
+
13
+ $ gem install soap4r-middleware
14
+
15
+ Usage
16
+ -----
17
+
18
+ First, get yourself some Soap4r endpoint code. The easiest way to do
19
+ this is to generate it from a WSDL file. Details are in the Soap4r
20
+ documentation, or see http://dev.ctor.org/soap4r/wiki/HowtouseWSDL4R ,
21
+ but basically:
22
+
23
+ $ wsdl2ruby.rb --wsdl /path/to/definiton.wsdl --type server
24
+
25
+ You'll get some generated files. One of them will be named
26
+ like `*APIService.rb`, near the bottom will be a class of the same name.
27
+ To enable middleware functionality, you want to copy this class'
28
+ initialization code into a new class that subclasses `Soap4r::Middleware::Base`, and replace the initialize method with a block passed to `setup`. For instance:
29
+
30
+ gem 'soap4r-middleware' # or use Bundler
31
+ require 'soap4r-middleware'
32
+
33
+ class MyAPIMiddleware < Soap4r::Middleware::Base
34
+ setup do
35
+ self.endpoint = %r{^/url/to/soap/endpoint/}
36
+ servant MyAPIPort.new
37
+ MyAPIPort::Methods.each do |definitions|
38
+ opt = definitions.last
39
+ if opt[:request_style] == :document
40
+ @router.add_document_operation(servant, *definitions)
41
+ else
42
+ @router.add_rpc_operation(servant, *definitions)
43
+ end
44
+ end
45
+ self.mapping_registry = UrnMyAPIMappingRegistry::EncodedRegistry
46
+ self.literal_mapping_registry = UrnMyAPIMappingRegistry::LiteralRegistry
47
+ end
48
+ end
49
+
50
+ Then use this middleware anywhere you'd use a Rack middleware. It
51
+ doubles as a Rack application as well, so you can host it directly using
52
+ `run MyAPIMiddleware.new` in your `rackup.ru` file.
53
+
54
+ ### TODO
55
+
56
+ I guess I could wrap `wsdl2ruby.rb` and make this automatic.
57
+
58
+ ### Wait, This is For Seriously??
59
+
60
+ Sometimes you just gotta SOAP. Might as well make it suck as little as
61
+ possible.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,171 @@
1
+ class Soap4r::Middleware::Base
2
+ include SOAP
3
+
4
+ def self.setup
5
+ raise("Please subclass first") if self == Soap4r::Middleware::Base
6
+ @router = ::SOAP::RPC::Router.new(self.class.name)
7
+ yield self
8
+ self
9
+ end
10
+
11
+ def self.router
12
+ @router
13
+ end
14
+
15
+ def self.endpoint=(regex)
16
+ @endpoint = regex
17
+ end
18
+
19
+ def self.endpoint
20
+ @endpoint
21
+ end
22
+
23
+ def initialize(app = nil)
24
+ @app = app
25
+ @endpoint = self.class.endpoint
26
+ unless @endpoint.is_a?(Regexp)
27
+ raise ArgumentError, "Endpoint has not been defined"
28
+ end
29
+ end
30
+
31
+ def call(env)
32
+ if env['PATH_INFO'].match(@endpoint)
33
+ handle(env)
34
+ else
35
+ # we can act as both a middleware and an app
36
+ @app ?
37
+ @app.call(env) :
38
+ [ 404, { "Content-Type" => "text/html" }, "Not Found" ]
39
+ end
40
+ end
41
+
42
+ def handle(env)
43
+ # yeah, all soap calls are over POST
44
+ if env['REQUEST_METHOD'] != 'POST'
45
+ return 405, { 'Content-Length' => '0',
46
+ 'Allow' => 'POST',
47
+ 'Content-Type' => 'text/plain' }, []
48
+ end
49
+
50
+ conn_data = ::SOAP::StreamHandler::ConnectionData.new
51
+ setup_request(conn_data, env)
52
+ conn_data = self.class.router.route(conn_data)
53
+ status, headers, body = setup_response(conn_data, env)
54
+ [ status, headers, body ]
55
+ rescue
56
+ raise # TODO -- do we 500 right here, or let the exception bubble up?
57
+ end
58
+
59
+ def setup_request(conn_data, env)
60
+ # TODO: we're reading the whole input here, which kind of stinks if rack is
61
+ # reading from the client on demand. We can't just pass in the rack input
62
+ # object, since REXML needs an IO that responds to :eof? -- we'd need a
63
+ # wrapper IO-like object.
64
+ conn_data.receive_string = env['rack.input'].read
65
+ conn_data.receive_contenttype = env['CONTENT_TYPE']
66
+ conn_data.soapaction = parse_soapaction(env['HTTP_SOAPAction'])
67
+ end
68
+
69
+ def setup_response(conn_data, env)
70
+ status = 200
71
+ headers = {}
72
+ body = []
73
+ headers['content-type'] = conn_data.send_contenttype
74
+ # TODO: cookies?
75
+ if conn_data.is_nocontent
76
+ status = 202 # ACCEPTED
77
+ elsif conn_data.is_fault
78
+ status = 500 # INTERNAL_SERVER_ERROR
79
+ else
80
+ body = conn_data.send_string
81
+ end
82
+ return status, headers, body
83
+ end
84
+
85
+ def parse_soapaction(soapaction)
86
+ if !soapaction.nil? and !soapaction.empty?
87
+ if /\A"(.+)"\z/ =~ soapaction
88
+ return $1
89
+ end
90
+ end
91
+ nil
92
+ end
93
+
94
+ class << self
95
+
96
+ # SOAP interface
97
+
98
+ def mapping_registry
99
+ router.mapping_registry
100
+ end
101
+
102
+ def mapping_registry=(mapping_registry)
103
+ router.mapping_registry = mapping_registry
104
+ end
105
+
106
+ def literal_mapping_registry
107
+ router.literal_mapping_registry
108
+ end
109
+
110
+ def literal_mapping_registry=(literal_mapping_registry)
111
+ router.literal_mapping_registry = literal_mapping_registry
112
+ end
113
+
114
+ def generate_explicit_type
115
+ router.generate_explicit_type
116
+ end
117
+
118
+ def generate_explicit_type=(generate_explicit_type)
119
+ router.generate_explicit_type = generate_explicit_type
120
+ end
121
+
122
+ # servant entry interface
123
+
124
+ def add_rpc_servant(obj, namespace = self.default_namespace)
125
+ router.add_rpc_servant(obj, namespace)
126
+ end
127
+ alias add_servant add_rpc_servant
128
+
129
+ def add_headerhandler(obj)
130
+ router.add_headerhandler(obj)
131
+ end
132
+ alias add_rpc_headerhandler add_headerhandler
133
+
134
+ def filterchain
135
+ router.filterchain
136
+ end
137
+
138
+ # method entry interface
139
+
140
+ def add_rpc_method(obj, name, *param)
141
+ add_rpc_method_with_namespace_as(default_namespace, obj, name, name, *param)
142
+ end
143
+ alias add_method add_rpc_method
144
+
145
+ def add_rpc_method_as(obj, name, name_as, *param)
146
+ add_rpc_method_with_namespace_as(default_namespace, obj, name, name_as, *param)
147
+ end
148
+ alias add_method_as add_rpc_method_as
149
+
150
+ def add_rpc_method_with_namespace(namespace, obj, name, *param)
151
+ add_rpc_method_with_namespace_as(namespace, obj, name, name, *param)
152
+ end
153
+ alias add_method_with_namespace add_rpc_method_with_namespace
154
+
155
+ def add_rpc_method_with_namespace_as(namespace, obj, name, name_as, *param)
156
+ qname = XSD::QName.new(namespace, name_as)
157
+ soapaction = nil
158
+ param_def = SOAPMethod.derive_rpc_param_def(obj, name, *param)
159
+ router.add_rpc_operation(obj, qname, soapaction, name, param_def)
160
+ end
161
+ alias add_method_with_namespace_as add_rpc_method_with_namespace_as
162
+
163
+ def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
164
+ router.add_rpc_operation(receiver, qname, soapaction, name, param_def, opt)
165
+ end
166
+
167
+ def add_document_operation(receiver, soapaction, name, param_def, opt = {})
168
+ router.add_document_operation(receiver, soapaction, name, param_def, opt)
169
+ end
170
+ end # class << self
171
+ end
@@ -0,0 +1,5 @@
1
+ module Soap4r
2
+ module Middleware
3
+ VERSION = "0.8.0"
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ require 'soap/rpc/router'
2
+
3
+ module Soap4r
4
+ module Middleware
5
+ end
6
+ end
7
+
8
+ require 'soap4r-middleware/base'
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "soap4r-middleware/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "soap4r-middleware"
7
+ s.version = Soap4r::Middleware::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Brian Palmer"]
10
+ s.email = ["brian@codekitchen.net"]
11
+ s.homepage = "https://www.github.com/codekitchen/soap4r-middleware"
12
+ s.summary = %q{Provides a Rack middleware for exposing SOAP server endpoints}
13
+ s.description = %q{Sometimes, you just gotta SOAP.}
14
+
15
+ s.rubyforge_project = "soap4r-middleware"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency 'soap4r', '~> 1.5'
23
+ end
metadata ADDED
@@ -0,0 +1,89 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: soap4r-middleware
3
+ version: !ruby/object:Gem::Version
4
+ hash: 63
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 8
9
+ - 0
10
+ version: 0.8.0
11
+ platform: ruby
12
+ authors:
13
+ - Brian Palmer
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-08 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: soap4r
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 5
30
+ segments:
31
+ - 1
32
+ - 5
33
+ version: "1.5"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: Sometimes, you just gotta SOAP.
37
+ email:
38
+ - brian@codekitchen.net
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - .gitignore
47
+ - Gemfile
48
+ - README.md
49
+ - Rakefile
50
+ - lib/soap4r-middleware.rb
51
+ - lib/soap4r-middleware/base.rb
52
+ - lib/soap4r-middleware/version.rb
53
+ - soap4r-middleware.gemspec
54
+ has_rdoc: true
55
+ homepage: https://www.github.com/codekitchen/soap4r-middleware
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options: []
60
+
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ none: false
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ hash: 3
69
+ segments:
70
+ - 0
71
+ version: "0"
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ hash: 3
78
+ segments:
79
+ - 0
80
+ version: "0"
81
+ requirements: []
82
+
83
+ rubyforge_project: soap4r-middleware
84
+ rubygems_version: 1.3.7
85
+ signing_key:
86
+ specification_version: 3
87
+ summary: Provides a Rack middleware for exposing SOAP server endpoints
88
+ test_files: []
89
+