lib/savon/soap.rb in savon-0.7.5 vs lib/savon/soap.rb in savon-0.7.6
- old
+ new
@@ -1,24 +1,134 @@
module Savon
- # == Savon::SOAP
+ # = Savon::SOAP
#
- # Represents the SOAP parameters and envelope.
+ # Savon::SOAP represents the SOAP request. Pass a block to your SOAP call and the SOAP object is
+ # passed to it as the first argument. The object allows setting the SOAP version, header, body
+ # and namespaces per request.
+ #
+ # == Body
+ #
+ # The body method lets you specify parameters to be received by the SOAP action.
+ #
+ # You can either pass in a hash (which will be translated to XML via Hash.to_soap_xml):
+ #
+ # response = client.get_user_by_id do |soap|
+ # soap.body = { :id => 123 }
+ # end
+ #
+ # Or a string containing the raw XML:
+ #
+ # response = client.get_user_by_id do |soap|
+ # soap.body = "<id>123</id>"
+ # end
+ #
+ # Request output:
+ #
+ # <env:Envelope
+ # xmlns:wsdl="http://example.com/user/1.0/UserService"
+ # xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
+ # <env:Body>
+ # <wsdl:getUserById><id>123</id></wsdl:getUserById>
+ # </env:Body>
+ # </env:Envelope>
+ #
+ # Please look at the documentation of Hash.to_soap_xml for some more information.
+ #
+ # == Version
+ #
+ # Savon defaults to SOAP 1.1. In case your service uses SOAP 1.2, you can use the version method
+ # to change the default per request.
+ #
+ # response = client.get_all_users do |soap|
+ # soap.version = 2
+ # end
+ #
+ # You can also change the default to SOAP 1.2 for all request:
+ #
+ # Savon::SOAP.version = 2
+ #
+ # == Header
+ #
+ # If you need to add custom XML into the SOAP header, you can use the header method.
+ #
+ # The value is expected to be a hash (which will be translated to XML via Hash.to_soap_xml):
+ #
+ # response = client.get_all_users do |soap|
+ # soap.header["specialApiKey"] = "secret"
+ # end
+ #
+ # Or a string containing the raw XML:
+ #
+ # response = client.get_all_users do |soap|
+ # soap.header = "<specialApiKey>secret</specialApiKey>"
+ # end
+ #
+ # Request output:
+ #
+ # <env:Envelope
+ # xmlns:wsdl="http://example.com/user/1.0/UserService"
+ # xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
+ # <env:Header>
+ # <specialApiKey>secret</specialApiKey>
+ # </env:Header>
+ # <env:Body>
+ # <wsdl:getAllUsers></wsdl:getAllUsers>
+ # </env:Body>
+ # </env:Envelope>
+ #
+ # == Namespaces
+ #
+ # The namespaces method contains a hash of attributes for the SOAP envelope. You can overwrite it
+ # or add additional attributes.
+ #
+ # response = client.get_all_users do |soap|
+ # soap.namespaces["xmlns:domains"] = "http://domains.example.com"
+ # end
+ #
+ # Request output:
+ #
+ # <env:Envelope
+ # xmlns:wsdl="http://example.com/user/1.0/UserService"
+ # xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
+ # xmlns:domains="http://domains.example.com">
+ # <env:Body>
+ # <wsdl:getAllUsers></wsdl:getAllUsers>
+ # </env:Body>
+ # </env:Envelope>
+ #
+ # == Input
+ #
+ # You can change the name of the SOAP input tag in case you need to.
+ #
+ # response = client.get_all_users do |soap|
+ # soap.input = "GetAllUsersRequest"
+ # end
+ #
+ # Request output:
+ #
+ # <env:Envelope
+ # xmlns:wsdl="http://example.com/user/1.0/UserService"
+ # xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
+ # <env:Body>
+ # <wsdl:GetAllUsersRequest></wsdl:GetAllUsersRequest>
+ # </env:Body>
+ # </env:Envelope>
class SOAP
+ # Supported SOAP versions.
+ Versions = [1, 2]
+
# SOAP namespaces by SOAP version.
Namespace = {
1 => "http://schemas.xmlsoap.org/soap/envelope/",
2 => "http://www.w3.org/2003/05/soap-envelope"
}
# Content-Types by SOAP version.
ContentType = { 1 => "text/xml", 2 => "application/soap+xml" }
- # Supported SOAP versions.
- Versions = [1, 2]
-
# SOAP xs:dateTime format.
DateTimeFormat = "%Y-%m-%dT%H:%M:%SZ"
# SOAP xs:dateTime Regexp.
DateTimeRegexp = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/
@@ -34,36 +144,36 @@
# Sets the global SOAP version.
def self.version=(version)
@@version = version if Versions.include? version
end
- # Sets the global SOAP header. Expected to be a Hash that can be translated
- # to XML via Hash.to_soap_xml or any other Object responding to to_s.
+ # Sets the global SOAP header. Expected to be a Hash that can be translated to XML via
+ # Hash.to_soap_xml or any other Object responding to to_s.
def self.header=(header)
@@header = header
end
# Returns the global SOAP header. Defaults to an empty Hash.
def self.header
@@header ||= {}
end
- # Sets the global namespaces. Expected to be a Hash containing the
- # namespaces (keys) and the corresponding URI's (values).
+ # Sets the global namespaces. Expected to be a Hash containing the namespaces (keys) and the
+ # corresponding URI's (values).
def self.namespaces=(namespaces)
@@namespaces = namespaces if namespaces.kind_of? Hash
end
- # Returns the global namespaces. A Hash containing the namespaces (keys)
- # and the corresponding URI's (values).
+ # Returns the global namespaces. A Hash containing the namespaces (keys) and the corresponding
+ # URI's (values).
def self.namespaces
@@namespaces ||= {}
end
- # Initialzes the SOAP object.
- def initialize(operation, endpoint)
- @action, @input = operation[:action], operation[:input]
+ # Initialzes the SOAP object. Expects a SOAP +operation+ Hash along with an +endpoint+.
+ def initialize(action, input, endpoint)
+ @action, @input = action, input
@endpoint = endpoint.kind_of?(URI) ? endpoint : URI(endpoint)
@builder = Builder::XmlMarkup.new
end
# Sets the WSSE options.
@@ -86,34 +196,38 @@
end
# Accessor for the SOAP endpoint.
attr_accessor :endpoint
- # Sets the SOAP header. Expected to be a Hash that can be translated
- # to XML via Hash.to_soap_xml or any other Object responding to to_s.
+ # Sets the SOAP header. Expected to be a Hash that can be translated to XML via Hash.to_soap_xml
+ # or any other Object responding to to_s.
attr_writer :header
# Returns the SOAP header. Defaults to an empty Hash.
def header
@header ||= {}
end
- # Sets the SOAP body. Expected to be a Hash that can be translated to
- # XML via Hash.to_soap_xml or any other Object responding to to_s.
- attr_writer :body
+ # Accessor for the SOAP body. Expected to be a Hash that can be translated to XML via Hash.to_soap_xml
+ # or any other Object responding to to_s.
+ attr_accessor :body
- # Sets the namespaces. Expected to be a Hash containing the namespaces
- # (keys) and the corresponding URI's (values).
+ # Accessor for overwriting the default SOAP request. Let's you specify completely custom XML.
+ attr_accessor :xml
+
+ # Sets the namespaces. Expected to be a Hash containing the namespaces (keys) and the
+ # corresponding URI's (values).
attr_writer :namespaces
- # Returns the namespaces. A Hash containing the namespaces (keys)
- # and the corresponding URI's (values).
+ # Returns the namespaces. A Hash containing the namespaces (keys) and the corresponding URI's
+ # (values). Defaults to a Hash containing an +xmlns:env+ key and the namespace for the current
+ # SOAP version.
def namespaces
@namespaces ||= { "xmlns:env" => Namespace[version] }
end
- # Convenience method for setting the "xmlns:wsdl" namespace.
+ # Convenience method for setting the +xmlns:wsdl+ namespace.
def namespace=(namespace)
namespaces["xmlns:wsdl"] = namespace
end
# Sets the SOAP version.
@@ -126,62 +240,63 @@
@version ||= self.class.version
end
# Returns the SOAP envelope XML.
def to_xml
- unless @xml_body
- @xml_body = @builder.env :Envelope, all_namespaces do |xml|
- xml.env(:Header) { xml << all_header } unless all_header.empty?
+ unless @xml
+ @builder.instruct!
+ @xml = @builder.env :Envelope, merged_namespaces do |xml|
+ xml.env(:Header) { xml << merged_header } unless merged_header.empty?
xml_body xml
end
end
- @xml_body
+ @xml
end
private
# Returns a String containing the global and per request header.
- def all_header
+ def merged_header
if self.class.header.kind_of?(Hash) && header.kind_of?(Hash)
- custom_header = self.class.header.merge(header).to_soap_xml
+ merged_header = self.class.header.merge(header).to_soap_xml
else
- custom_header = self.class.header.to_s + header.to_s
+ global_header = self.class.header.to_soap_xml rescue self.class.header.to_s
+ request_header = header.to_soap_xml rescue header.to_s
+ merged_header = global_header + request_header
end
- custom_header + wsse_header
+ merged_header + wsse_header
end
# Returns the WSSE header or an empty String in case WSSE was not set.
def wsse_header
@wsse.respond_to?(:header) ? @wsse.header : ""
end
# Adds a SOAP XML body to a given +xml+ Object.
def xml_body(xml)
xml.env(:Body) do
- xml.tag!(:wsdl, *input_array) do
- xml << (@body.to_soap_xml rescue @body.to_s)
- end
+ xml.tag!(:wsdl, *input_array) { xml << (@body.to_soap_xml rescue @body.to_s) }
end
end
# Returns a Hash containing the global and per request namespaces.
- def all_namespaces
+ def merged_namespaces
self.class.namespaces.merge namespaces
end
- # Returns an Array of SOAP input names to append to the :wsdl namespace.
- # Defaults to use the name of the SOAP action and may be an empty Array
- # in case the specified SOAP input seems invalid.
+ # Returns an Array of SOAP input names to append to the wsdl namespace. Defaults to use the
+ # name of the SOAP action. May return an empty Array in case the specified SOAP input seems
+ # to be invalid.
def input_array
- if !input.blank? && input.kind_of?(Array)
+ if input.kind_of?(Array) && !input.blank?
[input[0].to_sym, input[1]]
elsif !input.blank?
[input.to_sym]
- elsif action.blank?
+ elsif !action.blank?
[action.to_sym]
else
[]
end
end
end
-end
+end
\ No newline at end of file