soap4r-middleware 0.8.1 → 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.
@@ -2,6 +2,177 @@ require 'soap/rpc/router'
2
2
 
3
3
  module Soap4r
4
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
+ [ 404, { "Content-Type" => "text/html" }, "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, { 'Content-Length' => '0',
30
+ 'Allow' => 'POST',
31
+ 'Content-Type' => 'text/plain' }, []
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
5
176
  end
6
177
  end
7
178
 
@@ -1,176 +1,3 @@
1
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
- # rather than sending the 500 here, let's bubble up the exception so the
79
- # parent application can do with it what it will. The only downside is
80
- # soap4r has already converted the exception into a soap response body at
81
- # this point, which isn't what we want at all.
82
- # maybe someday i'll re-parse the response or something. but not today.
83
- raise conn_data.send_string
84
- else
85
- body = conn_data.send_string
86
- end
87
- return status, headers, body
88
- end
89
-
90
- def parse_soapaction(soapaction)
91
- if !soapaction.nil? and !soapaction.empty?
92
- if /\A"(.+)"\z/ =~ soapaction
93
- return $1
94
- end
95
- end
96
- nil
97
- end
98
-
99
- class << self
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 # class << self
2
+ include ::Soap4r::Middleware
176
3
  end
@@ -1,5 +1,5 @@
1
1
  module Soap4r
2
2
  module Middleware
3
- VERSION = "0.8.1"
3
+ VERSION = "0.8.2"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: soap4r-middleware
3
3
  version: !ruby/object:Gem::Version
4
- hash: 61
4
+ hash: 59
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 8
9
- - 1
10
- version: 0.8.1
9
+ - 2
10
+ version: 0.8.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - Brian Palmer
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-03-09 00:00:00 -07:00
18
+ date: 2011-03-10 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency