soap4r-middleware-192 0.8.2

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.
@@ -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
@@ -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.
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,179 @@
1
+ require 'soap/rpc/router'
2
+
3
+ module Soap4r
4
+ module Middleware
5
+ include SOAP
6
+
7
+ def self.included(klass)
8
+ klass.send(:extend, ::Soap4r::Middleware::ClassMethods)
9
+ end
10
+
11
+ def initialize(app = nil)
12
+ @app = app
13
+ end
14
+
15
+ def call(env)
16
+ if env['PATH_INFO'].match(self.class.endpoint)
17
+ handle(env)
18
+ else
19
+ # we can act as both a middleware and an app
20
+ @app ?
21
+ @app.call(env) :
22
+ ( return 404, { "Content-Type" => "text/plain" }, ["404 - Not Found"] )
23
+ end
24
+ end
25
+
26
+ def handle(env)
27
+ # yeah, all soap calls are over POST
28
+ if env['REQUEST_METHOD'] != 'POST'
29
+ return 405, {
30
+ 'Allow' => 'POST',
31
+ 'Content-Type' => 'text/plain' }, ["405 - Method Not Allowed"]
32
+ end
33
+
34
+ conn_data = ::SOAP::StreamHandler::ConnectionData.new
35
+ setup_request(conn_data, env)
36
+ conn_data = self.class.router.route(conn_data)
37
+ status, headers, body = setup_response(conn_data, env)
38
+ [ status, headers, body ]
39
+ rescue
40
+ raise # TODO -- do we 500 right here, or let the exception bubble up?
41
+ end
42
+
43
+ def setup_request(conn_data, env)
44
+ # TODO: we're reading the whole input here, which kind of stinks if rack is
45
+ # reading from the client on demand. We can't just pass in the rack input
46
+ # object, since REXML needs an IO that responds to :eof? -- we'd need a
47
+ # wrapper IO-like object.
48
+ conn_data.receive_string = env['rack.input'].read
49
+ conn_data.receive_contenttype = env['CONTENT_TYPE']
50
+ conn_data.soapaction = parse_soapaction(env['HTTP_SOAPAction'])
51
+ end
52
+
53
+ def setup_response(conn_data, env)
54
+ status = 200
55
+ headers = {}
56
+ body = []
57
+ headers['content-type'] = conn_data.send_contenttype
58
+ # TODO: cookies?
59
+ if conn_data.is_nocontent
60
+ status = 202 # ACCEPTED
61
+ elsif conn_data.is_fault
62
+ # rather than sending the 500 here, let's bubble up the exception so the
63
+ # parent application can do with it what it will. The only downside is
64
+ # soap4r has already converted the exception into a soap response body at
65
+ # this point, which isn't what we want at all.
66
+ # maybe someday i'll re-parse the response or something. but not today.
67
+ raise conn_data.send_string
68
+ else
69
+ body << conn_data.send_string
70
+ end
71
+ return status, headers, body
72
+ end
73
+
74
+ def parse_soapaction(soapaction)
75
+ if !soapaction.nil? and !soapaction.empty?
76
+ if /\A"(.+)"\z/ =~ soapaction
77
+ return $1
78
+ end
79
+ end
80
+ nil
81
+ end
82
+
83
+ module ClassMethods
84
+ def setup
85
+ @router = ::SOAP::RPC::Router.new(self.class.name)
86
+ yield self
87
+ end
88
+
89
+ def router
90
+ @router
91
+ end
92
+
93
+ def endpoint=(regex)
94
+ @endpoint = regex
95
+ end
96
+
97
+ def endpoint
98
+ @endpoint
99
+ end
100
+
101
+ # SOAP interface
102
+
103
+ def mapping_registry
104
+ router.mapping_registry
105
+ end
106
+
107
+ def mapping_registry=(mapping_registry)
108
+ router.mapping_registry = mapping_registry
109
+ end
110
+
111
+ def literal_mapping_registry
112
+ router.literal_mapping_registry
113
+ end
114
+
115
+ def literal_mapping_registry=(literal_mapping_registry)
116
+ router.literal_mapping_registry = literal_mapping_registry
117
+ end
118
+
119
+ def generate_explicit_type
120
+ router.generate_explicit_type
121
+ end
122
+
123
+ def generate_explicit_type=(generate_explicit_type)
124
+ router.generate_explicit_type = generate_explicit_type
125
+ end
126
+
127
+ # servant entry interface
128
+
129
+ def add_rpc_servant(obj, namespace = self.default_namespace)
130
+ router.add_rpc_servant(obj, namespace)
131
+ end
132
+ alias add_servant add_rpc_servant
133
+
134
+ def add_headerhandler(obj)
135
+ router.add_headerhandler(obj)
136
+ end
137
+ alias add_rpc_headerhandler add_headerhandler
138
+
139
+ def filterchain
140
+ router.filterchain
141
+ end
142
+
143
+ # method entry interface
144
+
145
+ def add_rpc_method(obj, name, *param)
146
+ add_rpc_method_with_namespace_as(default_namespace, obj, name, name, *param)
147
+ end
148
+ alias add_method add_rpc_method
149
+
150
+ def add_rpc_method_as(obj, name, name_as, *param)
151
+ add_rpc_method_with_namespace_as(default_namespace, obj, name, name_as, *param)
152
+ end
153
+ alias add_method_as add_rpc_method_as
154
+
155
+ def add_rpc_method_with_namespace(namespace, obj, name, *param)
156
+ add_rpc_method_with_namespace_as(namespace, obj, name, name, *param)
157
+ end
158
+ alias add_method_with_namespace add_rpc_method_with_namespace
159
+
160
+ def add_rpc_method_with_namespace_as(namespace, obj, name, name_as, *param)
161
+ qname = XSD::QName.new(namespace, name_as)
162
+ soapaction = nil
163
+ param_def = SOAPMethod.derive_rpc_param_def(obj, name, *param)
164
+ router.add_rpc_operation(obj, qname, soapaction, name, param_def)
165
+ end
166
+ alias add_method_with_namespace_as add_rpc_method_with_namespace_as
167
+
168
+ def add_rpc_operation(receiver, qname, soapaction, name, param_def, opt = {})
169
+ router.add_rpc_operation(receiver, qname, soapaction, name, param_def, opt)
170
+ end
171
+
172
+ def add_document_operation(receiver, soapaction, name, param_def, opt = {})
173
+ router.add_document_operation(receiver, soapaction, name, param_def, opt)
174
+ end
175
+ end # ClassMethods
176
+ end
177
+ end
178
+
179
+ require 'soap4r-middleware/base'
@@ -0,0 +1,3 @@
1
+ class Soap4r::Middleware::Base
2
+ include ::Soap4r::Middleware
3
+ end
@@ -0,0 +1,5 @@
1
+ module Soap4r
2
+ module Middleware
3
+ VERSION = "0.8.2"
4
+ end
5
+ end
@@ -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-192"
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 'rubyjedi-soap4r', '~> 1.5'
23
+ end
metadata ADDED
@@ -0,0 +1,66 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: soap4r-middleware-192
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Brian Palmer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-10-06 00:00:00.000000000 +04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rubyjedi-soap4r
17
+ requirement: &15804500 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '1.5'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *15804500
26
+ description: Sometimes, you just gotta SOAP.
27
+ email:
28
+ - brian@codekitchen.net
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - README.md
36
+ - Rakefile
37
+ - lib/soap4r-middleware.rb
38
+ - lib/soap4r-middleware/base.rb
39
+ - lib/soap4r-middleware/version.rb
40
+ - soap4r-middleware.gemspec
41
+ has_rdoc: true
42
+ homepage: https://www.github.com/codekitchen/soap4r-middleware
43
+ licenses: []
44
+ post_install_message:
45
+ rdoc_options: []
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ none: false
56
+ requirements:
57
+ - - ! '>='
58
+ - !ruby/object:Gem::Version
59
+ version: '0'
60
+ requirements: []
61
+ rubyforge_project: soap4r-middleware
62
+ rubygems_version: 1.6.2
63
+ signing_key:
64
+ specification_version: 3
65
+ summary: Provides a Rack middleware for exposing SOAP server endpoints
66
+ test_files: []