Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
require 'rubygems'
require 'mail'
require 'savon'
# I needed to send "SOAP with Attachments" and found soap4r too horrible.
# Since I saw no support for it in Savon I tried to hack something together
# to see if it could be done. I share that messy code here
# this is updated for Savon 0.8.1
module Savon
module SOAP
class Part < Mail::Part
# placeholder for SOAP-sepcific improvements
end
class XML
attr_accessor :parts_sort_order
# adds a Part object to the current SOAP "message"
# Parts are really attachments
def add_part(part)
@parts ||= Array.new
@parts << part
end
# check if any parts have been added
def has_parts?
@parts ||= Array.new
!@parts.empty?
end
# returns the mime message for a multipart request
def request_message
if @parts.empty?
return nil
end
@request_message = Part.new do
content_type 'multipart/related; type="text/xml"'
end
soap_body = self.to_xml
soap_message = Part.new do
content_type 'text/xml; charset=utf-8'
add_content_transfer_encoding
body soap_body
end
@request_message.add_part(soap_message)
@parts.each do |part|
@request_message.add_part(part)
end
#puts @request_message
@request_message
end
end
class Request
def setup(request, soap)
request.url = soap.endpoint
if soap.has_parts? # do multipart stuff if soap has parts
request_message = soap.request_message
# takes relevant http headers from the "Mail" message and makes them Net::HTTP compatible
request.headers["Content-Type"] ||= ContentType[soap.version]
request.headers.delete "SOAPAction"
request_message.header.fields.each do |field|
request.headers[field.name] = field.to_s
end
request_message.body.set_sort_order soap.parts_sort_order if soap.parts_sort_order && soap.parts_sort_order.any?
puts request.inspect
request.body = request_message.body.encoded
else
request.headers["Content-Type"] ||= ContentType[soap.version]
request.body = soap.to_xml
end
request
end
end
end
end
# Usage Example
my_header = {'myns:SomeHeader' => 'Some Header Data'}
my_body = {
'myns:SomeBodyTag' => 'Some Body Data',
'myns:Attachment' => 'attachment_name.jpg'
}
mime_attachment = Savon::Part.new do
content_type 'image/jpeg'
cid= 'attachment_name.jpg' # this should work...
body File.read('path/to/an/image.jpg').force_encoding("BINARY")
end
# ...but this is needed for a working cid
mime_attachment.add_content_id 'attachment_name.jpg'
soapclient = Savon::Client.new do
wsdl.endpoint = "http://example.com/api/soap"
wsdl.namespace = "http://example.com/some/namespace"
http.auth.basic 'uname', 'pass' # if you are allowed to post attachments you are likely to need a login
end
response = soapclient.request :myns, :example_action, 'xmlns:mm7'=>'http://example.com/some/namespace2' do
soap.namespaces["xmlns:mm7"] = "http://example.com/some/namespace"
soap.header = my_header
soap.body = my_body
soap.add_part(mime_attachment)
end
# results:
=begin
----==_mimepart_4ca34d61dbe3f_7d880445d4c280f3
Date: Wed, 29 Sep 2010 16:29:54 +0200
Message-ID: <4ca34d626abd2_7d880445d4c28299@localhost>
Mime-Version: 1.0
Content-Type: text/xml;
charset=utf-8
Content-Transfer-Encoding: 7bit
Content-ID: <4ca34d6269827_7d880445d4c28127@localhost>
<?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" xmlns:wsdl="http://example.com/some/namespace"><env:Header><myns:SomeHeader>Some Header Data</myns:SomeHeader></env:Header><env:Body><myns:exampleAction><myns:SomeBodyTag>Some Body Data</myns:SomeBodyTag><myns:Attachment>attachment_name.jpg</myns:Attachment></myns:exampleAction></env:Body></env:Envelope>
----==_mimepart_4ca34d61dbe3f_7d880445d4c280f3
Date: Wed, 29 Sep 2010 16:29:54 +0200
Message-ID: <4ca34d626d11a_7d880445d4c28477@localhost>
Mime-Version: 1.0
Content-Type: image/jpeg;
charset=UTF-8
Content-Transfer-Encoding: base64
Content-ID: <attachment_name.jpg>
/9j/4AAQSkZJRgABAgEBLAEsAAD/4RLmRXhpZgAATU0AKgAAAAgABwESAAMA
AAABAAEAAAEaAAUAAAABAAAAYgEbAAUAAAABAAAAagEoAAMAAAABAAIAAAEx
AAIAAAAeAAAAcgEyAAIAAAAUAAAAkIdpAAQAAAABAAAApAAAANAALcbAAAAn
... and so on until...
+7FWs2XxbwP3ZuLeB+7FWstftD5jNxbwP3Zaq3IbHqO2BX//2Q==
----==_mimepart_4ca34d61dbe3f_7d880445d4c280f3--
=end
@mikekirby

This comment has been minimized.

Copy link

@mikekirby mikekirby commented Sep 30, 2010

I am investigating MTOM for savon, thanks for posting your code.

@Xosmond

This comment has been minimized.

Copy link

@Xosmond Xosmond commented Oct 30, 2017

This code its too old, but there is a new PR for savon on: savonrb/savon#761

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment