troelskn-handsoap 0.3.8 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.yml +2 -2
- data/lib/handsoap/service.rb +76 -56
- data/lib/handsoap/xml_query_front.rb +7 -7
- metadata +4 -4
data/VERSION.yml
CHANGED
data/lib/handsoap/service.rb
CHANGED
@@ -24,40 +24,6 @@ module Handsoap
|
|
24
24
|
@xml_query_driver = Handsoap::XmlQueryFront.load_driver!(driver)
|
25
25
|
end
|
26
26
|
|
27
|
-
SOAP_NAMESPACE = { 1 => 'http://schemas.xmlsoap.org/soap/envelope/', 2 => 'http://www.w3.org/2003/05/soap-envelope' }
|
28
|
-
|
29
|
-
class Response
|
30
|
-
def initialize(http_body, soap_namespace)
|
31
|
-
@http_body = http_body
|
32
|
-
@soap_namespace = soap_namespace
|
33
|
-
@document = :lazy
|
34
|
-
@fault = :lazy
|
35
|
-
end
|
36
|
-
def document?
|
37
|
-
!! document
|
38
|
-
end
|
39
|
-
def document
|
40
|
-
if @document == :lazy
|
41
|
-
begin
|
42
|
-
@document = Handsoap::XmlQueryFront.parse_string(@http_body, Handsoap.xml_query_driver)
|
43
|
-
rescue Handsoap::XmlQueryFront::ParseError => ex
|
44
|
-
@document = nil
|
45
|
-
end
|
46
|
-
end
|
47
|
-
return @document
|
48
|
-
end
|
49
|
-
def fault?
|
50
|
-
!! fault
|
51
|
-
end
|
52
|
-
def fault
|
53
|
-
if @fault == :lazy
|
54
|
-
nodes = document? ? document.xpath('/env:Envelope/env:Body/descendant-or-self::env:Fault', { 'env' => @soap_namespace }) : []
|
55
|
-
@fault = nodes.any? ? Fault.from_xml(nodes.first, :namespace => @soap_namespace) : nil
|
56
|
-
end
|
57
|
-
return @fault
|
58
|
-
end
|
59
|
-
end
|
60
|
-
|
61
27
|
class Fault < Exception
|
62
28
|
attr_reader :code, :reason, :details
|
63
29
|
def initialize(code, reason, details)
|
@@ -91,18 +57,33 @@ module Handsoap
|
|
91
57
|
def self.logger=(io)
|
92
58
|
@@logger = io
|
93
59
|
end
|
60
|
+
# Sets the endpoint for the service.
|
61
|
+
# Arguments:
|
62
|
+
# :uri => endpoint uri of the service. Required.
|
63
|
+
# :version => 1 | 2
|
64
|
+
# :envelope_namespace => Namespace of SOAP-envelope
|
65
|
+
# :request_content_type => Content-Type of HTTP request.
|
66
|
+
# You must supply either :version or both :envelope_namspace and :request_content_type.
|
67
|
+
# :version is simply a shortcut for default values.
|
94
68
|
def self.endpoint(args = {})
|
95
|
-
@protocol_version = args[:version] || raise("Missing option :version")
|
96
69
|
@uri = args[:uri] || raise("Missing option :uri")
|
70
|
+
if args[:version]
|
71
|
+
soap_namespace = { 1 => 'http://schemas.xmlsoap.org/soap/envelope/', 2 => 'http://www.w3.org/2003/05/soap-envelope' }
|
72
|
+
raise("Unknown protocol version '#{@protocol_version.inspect}'") if soap_namespace[args[:version]].nil?
|
73
|
+
@envelope_namespace = soap_namespace[args[:version]]
|
74
|
+
@request_content_type = args[:version] == 1 ? "text/xml" : "application/soap+xml"
|
75
|
+
end
|
76
|
+
@envelope_namespace = args[:envelope_namespace] unless args[:envelope_namespace].nil?
|
77
|
+
@request_content_type = args[:request_content_type] unless args[:request_content_type].nil?
|
78
|
+
if @envelope_namespace.nil? || @request_content_type.nil?
|
79
|
+
raise("Missing option :envelope_namespace, :request_content_type or :version")
|
80
|
+
end
|
97
81
|
end
|
98
82
|
def self.envelope_namespace
|
99
|
-
|
100
|
-
raise "Unknown protocol version '#{@protocol_version.inspect}'"
|
101
|
-
end
|
102
|
-
SOAP_NAMESPACE[@protocol_version]
|
83
|
+
@envelope_namespace
|
103
84
|
end
|
104
85
|
def self.request_content_type
|
105
|
-
@
|
86
|
+
@request_content_type
|
106
87
|
end
|
107
88
|
def self.uri
|
108
89
|
@uri
|
@@ -158,6 +139,11 @@ module Handsoap
|
|
158
139
|
# You can override this to provide filtering and logging.
|
159
140
|
def on_before_dispatch
|
160
141
|
end
|
142
|
+
# Hook that is called after the http_client is created.
|
143
|
+
#
|
144
|
+
# You can override this to customize the http_client
|
145
|
+
def on_after_create_http_client(http_client)
|
146
|
+
end
|
161
147
|
# Hook that is called when there is a response.
|
162
148
|
#
|
163
149
|
# You can override this to register common namespaces, useful for parsing the document.
|
@@ -172,13 +158,18 @@ module Handsoap
|
|
172
158
|
# Hook that is called if the dispatch returns a +Fault+.
|
173
159
|
#
|
174
160
|
# Default behaviour is to raise the Fault, but you can override this to provide logging and more fine-grained handling faults.
|
161
|
+
#
|
162
|
+
# See also: parse_soap_fault
|
175
163
|
def on_fault(fault)
|
176
164
|
raise fault
|
177
165
|
end
|
178
166
|
# Hook that is called if the response does not contain a valid SOAP enevlope.
|
179
167
|
#
|
180
168
|
# Default behaviour is to raise an error
|
181
|
-
|
169
|
+
#
|
170
|
+
# Note that if your service has operations that are one-way, you shouldn't raise an error here.
|
171
|
+
# This is however a fairly exotic case, so that is why the default behaviour is to raise an error.
|
172
|
+
def on_missing_document(http_response_body)
|
182
173
|
raise "The response is not a valid SOAP envelope"
|
183
174
|
end
|
184
175
|
def debug(message = nil) #:nodoc:
|
@@ -195,17 +186,20 @@ module Handsoap
|
|
195
186
|
def send_http_request(uri, post_body, headers)
|
196
187
|
if Handsoap.http_driver == :curb
|
197
188
|
http_client = Curl::Easy.new(uri)
|
189
|
+
on_after_create_http_client(http_client)
|
198
190
|
http_client.headers = headers
|
199
191
|
http_client.http_post post_body
|
200
192
|
return { :status => http_client.response_code, :body => http_client.body_str, :content_type => http_client.content_type }
|
201
193
|
elsif Handsoap.http_driver == :httpclient
|
202
|
-
|
194
|
+
http_client = HTTPClient.new
|
195
|
+
on_after_create_http_client(http_client)
|
196
|
+
response = http_client.post(uri, post_body, headers)
|
203
197
|
return { :status => response.status, :body => response.content, :content_type => response.contenttype }
|
204
198
|
else
|
205
199
|
raise "Unknown http driver #{Handsoap.http_driver}"
|
206
200
|
end
|
207
201
|
end
|
208
|
-
# Send document and parses the response into a +
|
202
|
+
# Send document and parses the response into a +XmlQueryFront::XmlElement+ (XmlDocument)
|
209
203
|
def dispatch(doc, action)
|
210
204
|
on_before_dispatch
|
211
205
|
headers = {
|
@@ -229,18 +223,29 @@ module Handsoap
|
|
229
223
|
logger.puts "---"
|
230
224
|
logger.puts Handsoap.pretty_format_envelope(response[:body])
|
231
225
|
end
|
232
|
-
|
233
|
-
|
234
|
-
|
226
|
+
# Start the parsing pipe-line.
|
227
|
+
# There are various stages and hooks for each, so that you can override those in your service classes.
|
228
|
+
xml_document = parse_soap_response_document(response[:body])
|
229
|
+
soap_fault = parse_soap_fault(xml_document)
|
230
|
+
# Is the response a soap-fault?
|
231
|
+
unless soap_fault.nil?
|
232
|
+
return on_fault(soap_fault)
|
235
233
|
end
|
236
|
-
|
234
|
+
# Does the http-status indicate an error?
|
235
|
+
if response[:status] >= 400
|
237
236
|
return on_http_error(response[:status], response[:body])
|
238
237
|
end
|
239
|
-
|
240
|
-
|
238
|
+
# Does the response contain a valid xml-document?
|
239
|
+
if xml_document.nil?
|
240
|
+
return on_missing_document(response[:body])
|
241
|
+
end
|
242
|
+
# Everything seems in order.
|
243
|
+
on_response_document(xml_document)
|
244
|
+
# BC hack
|
245
|
+
def xml_document.document
|
246
|
+
self
|
241
247
|
end
|
242
|
-
|
243
|
-
return soap_response
|
248
|
+
return xml_document
|
244
249
|
end
|
245
250
|
# Creates a standard SOAP envelope and yields the +Body+ element.
|
246
251
|
def make_envelope # :yields: Handsoap::XmlMason::Element
|
@@ -258,6 +263,21 @@ module Handsoap
|
|
258
263
|
end
|
259
264
|
return doc
|
260
265
|
end
|
266
|
+
# String -> [XmlDocument | nil]
|
267
|
+
def parse_soap_response_document(http_body)
|
268
|
+
begin
|
269
|
+
Handsoap::XmlQueryFront.parse_string(http_body, Handsoap.xml_query_driver)
|
270
|
+
rescue Handsoap::XmlQueryFront::ParseError => ex
|
271
|
+
nil
|
272
|
+
end
|
273
|
+
end
|
274
|
+
# XmlDocument -> [Fault | nil]
|
275
|
+
def parse_soap_fault(document)
|
276
|
+
unless document.nil?
|
277
|
+
node = document.xpath('/env:Envelope/env:Body/descendant-or-self::env:Fault', { 'env' => self.class.envelope_namespace }).first
|
278
|
+
Fault.from_xml(node, :namespace => self.class.envelope_namespace) unless node.nil?
|
279
|
+
end
|
280
|
+
end
|
261
281
|
end
|
262
282
|
|
263
283
|
def self.pretty_format_envelope(xml_string)
|
@@ -312,7 +332,7 @@ module Handsoap
|
|
312
332
|
private
|
313
333
|
# Helper to serialize a node into a ruby string
|
314
334
|
#
|
315
|
-
# *deprecated*. Use Handsoap::XmlQueryFront::
|
335
|
+
# *deprecated*. Use Handsoap::XmlQueryFront::XmlElement#to_s
|
316
336
|
def xml_to_str(node, xquery = nil)
|
317
337
|
n = xquery ? node.xpath(xquery, ns).first : node
|
318
338
|
return if n.nil?
|
@@ -321,7 +341,7 @@ module Handsoap
|
|
321
341
|
alias_method :xml_to_s, :xml_to_str
|
322
342
|
# Helper to serialize a node into a ruby integer
|
323
343
|
#
|
324
|
-
# *deprecated*. Use Handsoap::XmlQueryFront::
|
344
|
+
# *deprecated*. Use Handsoap::XmlQueryFront::XmlElement#to_i
|
325
345
|
def xml_to_int(node, xquery = nil)
|
326
346
|
n = xquery ? node.xpath(xquery, ns).first : node
|
327
347
|
return if n.nil?
|
@@ -330,7 +350,7 @@ module Handsoap
|
|
330
350
|
alias_method :xml_to_i, :xml_to_int
|
331
351
|
# Helper to serialize a node into a ruby float
|
332
352
|
#
|
333
|
-
# *deprecated*. Use Handsoap::XmlQueryFront::
|
353
|
+
# *deprecated*. Use Handsoap::XmlQueryFront::XmlElement#to_f
|
334
354
|
def xml_to_float(node, xquery = nil)
|
335
355
|
n = xquery ? node.xpath(xquery, ns).first : node
|
336
356
|
return if n.nil?
|
@@ -339,7 +359,7 @@ module Handsoap
|
|
339
359
|
alias_method :xml_to_f, :xml_to_float
|
340
360
|
# Helper to serialize a node into a ruby boolean
|
341
361
|
#
|
342
|
-
# *deprecated*. Use Handsoap::XmlQueryFront::
|
362
|
+
# *deprecated*. Use Handsoap::XmlQueryFront::XmlElement#to_boolean
|
343
363
|
def xml_to_bool(node, xquery = nil)
|
344
364
|
n = xquery ? node.xpath(xquery, ns).first : node
|
345
365
|
return if n.nil?
|
@@ -347,7 +367,7 @@ module Handsoap
|
|
347
367
|
end
|
348
368
|
# Helper to serialize a node into a ruby Time object
|
349
369
|
#
|
350
|
-
# *deprecated*. Use Handsoap::XmlQueryFront::
|
370
|
+
# *deprecated*. Use Handsoap::XmlQueryFront::XmlElement#to_date
|
351
371
|
def xml_to_date(node, xquery = nil)
|
352
372
|
n = xquery ? node.xpath(xquery, ns).first : node
|
353
373
|
return if n.nil?
|
@@ -13,7 +13,7 @@ module Handsoap
|
|
13
13
|
# :nokogiri
|
14
14
|
# :libxml
|
15
15
|
#
|
16
|
-
# The resulting object is a wrapper, of the type Handsoap::XmlQueryFront::
|
16
|
+
# The resulting object is a wrapper, of the type Handsoap::XmlQueryFront::XmlElement.
|
17
17
|
#
|
18
18
|
module XmlQueryFront
|
19
19
|
|
@@ -65,7 +65,7 @@ module Handsoap
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
-
# NodeSelection is a wrapper around Array, that implicitly delegates
|
68
|
+
# NodeSelection is a wrapper around Array, that implicitly delegates XmlElement methods to the first element.
|
69
69
|
#
|
70
70
|
# It makes mapping code prettier, since you often need to access the first element of a selection.
|
71
71
|
class NodeSelection < Array
|
@@ -102,7 +102,7 @@ module Handsoap
|
|
102
102
|
end
|
103
103
|
|
104
104
|
# Wraps the underlying (native) xml driver, and provides a uniform interface.
|
105
|
-
module
|
105
|
+
module XmlElement
|
106
106
|
def initialize(element, namespaces = {})
|
107
107
|
@element = element
|
108
108
|
@namespaces = namespaces
|
@@ -116,7 +116,7 @@ module Handsoap
|
|
116
116
|
# Checks that an xpath-query doesn't refer to any undefined prefixes in +ns+
|
117
117
|
def assert_prefixes!(expression, ns)
|
118
118
|
expression.scan(/([a-zA-Z_][a-zA-Z0-9_.-]*):[^:]+/).map{|m| m[0] }.each do |prefix|
|
119
|
-
raise "Undefined prefix '#{prefix}'" if ns[prefix].nil?
|
119
|
+
raise "Undefined prefix '#{prefix}' in #{ns.inspect}" if ns[prefix].nil?
|
120
120
|
end
|
121
121
|
end
|
122
122
|
# Returns the value of the element as an integer.
|
@@ -203,7 +203,7 @@ module Handsoap
|
|
203
203
|
#
|
204
204
|
# http://libxml.rubyforge.org/
|
205
205
|
class LibXMLDriver
|
206
|
-
include
|
206
|
+
include XmlElement
|
207
207
|
def node_name
|
208
208
|
@element.name
|
209
209
|
end
|
@@ -236,7 +236,7 @@ module Handsoap
|
|
236
236
|
#
|
237
237
|
# http://www.germane-software.com/software/rexml/
|
238
238
|
class REXMLDriver
|
239
|
-
include
|
239
|
+
include XmlElement
|
240
240
|
def node_name
|
241
241
|
@element.name
|
242
242
|
end
|
@@ -274,7 +274,7 @@ module Handsoap
|
|
274
274
|
#
|
275
275
|
# http://nokogiri.rubyforge.org/nokogiri/
|
276
276
|
class NokogiriDriver
|
277
|
-
include
|
277
|
+
include XmlElement
|
278
278
|
def node_name
|
279
279
|
@element.name
|
280
280
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: troelskn-handsoap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Troels Knak-Nielsen
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-07-
|
12
|
+
date: 2009-07-31 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -33,7 +33,7 @@ files:
|
|
33
33
|
- lib/handsoap/service.rb
|
34
34
|
- lib/handsoap/xml_mason.rb
|
35
35
|
- lib/handsoap/xml_query_front.rb
|
36
|
-
has_rdoc:
|
36
|
+
has_rdoc: true
|
37
37
|
homepage: http://github.com/troelskn/handsoap
|
38
38
|
licenses:
|
39
39
|
post_install_message:
|
@@ -62,7 +62,7 @@ requirements:
|
|
62
62
|
rubyforge_project:
|
63
63
|
rubygems_version: 1.3.5
|
64
64
|
signing_key:
|
65
|
-
specification_version:
|
65
|
+
specification_version: 2
|
66
66
|
summary: Handsoap is a library for creating SOAP clients in Ruby
|
67
67
|
test_files: []
|
68
68
|
|