Read SOAP Responses
The response provides a few convenience methods for you to work with the XML in any way you want.
#header
Translates the response and returns the SOAP header as a Hash.
response.header # => { token: "secret" }
#body
Translates the response and returns the SOAP body as a Hash.
response.body # => { response: { success: true, name: "luke" } }
#to_hash is an alias for #body.
response.to_hash # => { response: { success: true, name: "luke" } }
#find
Walks the parsed envelope by tag name, returning the value at the given path or nil when a key
is missing. Useful when you want to drill into a deeply nested response without chaining []
through Hashes that might be nil.
response.find("Body", "AuthenticateResponse", "Return")
# => { success: true, name: "luke" }
#header and #body are thin wrappers around #find("Header") and #find("Body").
#to_array
Looks up a path under the SOAP body and always returns an Array. Returns [] if any key in the
path is nil, wraps a single Hash in an Array, and returns the existing Array compacted
otherwise. Handy when a service sometimes returns one element and sometimes many for the same
field.
response.to_array(:authenticate_response, :users, :user)
# => [{ id: 1, name: "luke" }, { id: 2, name: "lea" }]
response.to_array(:authenticate_response, :missing)
# => []
#full_hash
Translates the response and returns the full envelope as a Hash, including both header and body.
response.full_hash # => { envelope: { header: { ... }, body: { ... } } }
Note: response.hash still works but is deprecated and will be removed in a future release.
Savon uses Nori to translate the SOAP response XML to a Hash. You can change how the response is translated through a couple of global and local options. The following example shows the options available to configure Nori and their defaults.
client = Savon.client do
# Savon defaults to strip namespaces from the response
strip_namespaces true
# Savon defaults to convert response XML tags to snakecase Symbols
convert_response_tags_to ->(tag) { tag.snakecase.to_sym }
# Savon defaults to keeping xmlns:* attributes on response nodes
delete_namespace_attributes false
# Savon defaults to nil for empty XML tags (set to "" for an empty String)
empty_tag_value nil
# Savon defaults to converting dashes in response tag names to underscores
convert_dashes_to_underscores true
# Savon defaults to scrubbing invalid byte sequences from the response body
scrub_xml true
end
client.call(:operation) do
# Savon defaults to activate "advanced typecasting"
advanced_typecasting true
# Savon defaults to the Nokogiri parser
response_parser :nokogiri
end
These options map to Nori’s options and you can find more information about how they work in the README.
#to_xml
Returns the raw SOAP response. #to_s is an alias for the same value.
response.to_xml # => "<response><success>true</success><name>luke</name></response>"
response.to_s # same
#doc
Returns the SOAP response as a Nokogiri document.
response.doc # => #<Nokogiri::XML::Document:0x1017b4268 ...
#xpath
Delegates to Nokogiri’s xpath method.
response.xpath("//v1:authenticateResponse/return/success").first.inner_text.should == "true"
#multipart?
Returns true when the response Content-Type header starts with multipart.
response.multipart? # => true
#attachments
For multipart (MTOM) responses, returns the non-SOAP MIME parts as an
Array of Mail::Part objects. Returns [] when the response
isn’t multipart.
response.attachments.each do |part|
File.binwrite("downloads/#{part.filename}", part.body.decoded)
end
#http
Returns the underlying Savon::Transport::Response, which wraps the HTTP response
from the configured adapter (HTTPI or Faraday). It exposes code, headers, body,
and cookies for inspecting the transport-level response.
response.http # => Savon::Transport::Response
response.http.code # => 200
response.http.headers # => { "Content-Type" => "text/xml" }
response.http.body # => "<soap:Envelope>...</soap:Envelope>"
The shape of cookies depends on the transport. The HTTPI transport returns an Array
of HTTPI::Cookie objects, the Faraday transport returns a Hash of cookie names to values.
Both shapes can be passed back to the next request via the cookies local.
response.http.cookies # => [#<HTTPI::Cookie ...>] with transport: :httpi
response.http.cookies # => { "token" => "secret" } with transport: :faraday
In case you disabled the global :raise_errors option, you can ask the response for its state.
response.success? # => false
response.soap_fault? # => true
response.http_error? # => false
#successful? is an alias for #success?.
#soap_fault
Returns the Savon::SOAPFault for the response, or nil when no SOAP fault occurred. Useful as a conditional when raise_errors is disabled:
if fault = response.soap_fault
logger.warn "SOAP fault: #{fault.to_hash[:fault][:faultstring]}"
end
When raise_errors is enabled (the default), Savon raises the fault instead of returning it on the response.
#http_error
Returns the Savon::HTTPError for the response, or nil when the HTTP layer returned a successful status. Useful as a conditional when raise_errors is disabled:
if error = response.http_error
logger.warn "HTTP error: #{error.to_s}"
end
When raise_errors is enabled (the default), Savon raises the error instead of returning it on the response.