soap4r-middleware 0.8.1 → 0.8.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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