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 CHANGED
@@ -1,4 +1,4 @@
1
1
  ---
2
- :minor: 3
3
- :patch: 8
2
+ :minor: 4
3
+ :patch: 0
4
4
  :major: 0
@@ -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
- if SOAP_NAMESPACE[@protocol_version].nil?
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
- @protocol_version == 1 ? "text/xml" : "application/soap+xml"
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
- def on_missing_document(soap_response)
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
- response = HTTPClient.new.post(uri, post_body, headers)
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 +Response+
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
- soap_response = Response.new(response[:body], self.class.envelope_namespace)
233
- if soap_response.fault?
234
- return on_fault(soap_response.fault)
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
- if response[:status] >= 300
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
- unless soap_response.document?
240
- return on_missing_document(soap_response)
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
- on_response_document(soap_response.document)
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::BaseDriver#to_s
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::BaseDriver#to_i
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::BaseDriver#to_f
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::BaseDriver#to_boolean
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::BaseDriver#to_date
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::BaseDriver.
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 BaseDriver methods to the first element.
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 BaseDriver
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 BaseDriver
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 BaseDriver
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 BaseDriver
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.3.8
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-30 00:00:00 -07:00
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: false
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: 3
65
+ specification_version: 2
66
66
  summary: Handsoap is a library for creating SOAP clients in Ruby
67
67
  test_files: []
68
68