views:

209

answers:

2

I am using Savon to build the client, but want to kno how to create the actual envelope.

I am thinking of using Nokogiri XML Builder and just pass in the values, but not sure if that's the right way.

The SOAP envelope specs can be found here:

http://api.postalmethods.com/PostalWS.asmx?op=UploadFile

+2  A: 

My answer would be: Don't.

Savon will automatically create an envelope for you. You can pass whatever header and body you want, as arrays and hashes or XML strings. You can manipulate existing (default) namespaces and even override input actions. I'm not sure why anyone would need to construct a SOAP envelope in an XML parser such as nokogiri.

If your reason for not wanting to use Savon to construct the envelope is that it lacks some sort of functionality that the endpoint requires, let me know what the exact problem is. I've had to make a fairly significant amount of changes to Savon in the past to satisfy certain APIs, so chances are I already have a patch for you. And if not, I can certainly point you in the right direction in order for you to create your own patch.

And if you still need to construct an envelope outside of Savon, I'd recommend you not use Savon at all and simply send the XML through one of the many great http libs out there.

EDIT:

To illustrate how to use SOAP headers (and namespaces), you can include them as well as body in the request method:

client = Savon::Client.new "http://url.to/wsdl"

response = client.get do |soap|
  # Use merge! for namespaces so that you don't overwrite all of the original namespaces (while still retaining the ability to overwrite individual ones)
  soap.namespaces.merge!({
    "xmlns:xsi" => "http://www.w3.org/2001/XMLSchema-instance",
    "xmlns:xsd" => "http://www.w3.org/2001/XMLSchema"
  })

  # Use soap.header just like you would soap.body
  soap.header = {
    # SOAP header hash
  }

  # soap.body as usual
  soap.body = {
    # SOAP body hash
  }
end
vonconrad
thanks, I'd like to use Savon, but when I checked the documentation, I wasn't clear that it would put the <soap> headers in. Basically I only need to put body and anything outside of the soap headers using Savon?
Angela
Angela, it's very possible to specify SOAP headers. Please see my edit to see how.
vonconrad
+1  A: 

Savon treats inputs to SOAP services as Nested Hashes. The envelope is built by Savon so you generally shouldn't need to worry about it too much, if at all.

Have you actually managed to connect to the service yet and if not what errors are you getting?

If you have not yet connected and/or are having some problems with the concept of how to do this the following should get you started.

require 'savon'

client = Savon::Client.new http://api.postalmethods.com/PostalWS.asmx?wsdl
response = client.UploadFile do |soap|
  soap.body = {
    "Username" => "My User",
    "Password" => "My password"
    ...
  }
end

If you fill in the blanks at ... this should get you started although parsing the wsdl may not be the way to go forward in production. Have a look at the Savon documentation for specific issues that you get.

Edit

If you are not sure about Savon and SOAP then you could just use the postalmethods gem as described here, rather than re-inventing the wheel

Steve Weet
okay, great -- what does that means parsing the wsdl may not be the way to go forward in production? I saw that in the documentation.....
Angela
Well parsing the wsdl, which you are doing when you pass the wsdl to a new instance of Savon::Client is quite a costly exercise. You don't really need to do it once you have established the correct paramaters to pass. If I was you I would work on something like the above and see if it works and if it works quickly enough and then make a decision as to whether you can do it without the wsdl.
Steve Weet
I see -- so then if this works, I wouldn't use this code moving forward...?
Angela
Also, not sure how to debug the error I got back after using this code: REXML::ParseException (missing attribute quote
Angela
@Angela see the edit above
Steve Weet
Thanks...the gem doesn't have FileUpload method so I still need to figure this part out....thanks.
Angela