WhatfettleRuby Net::HTTP and SOAPAction

So you want to spurn SOAP4r and http-access2 and espouse Ruby's builtin Net::HTTP class? But yes, it is strange how headers such as SOAPAction get munged into Soapaction and rejected by many SOAP toolkits. Don't spill yer chunky-bacon, try my quick and dirty work-round:

require 'rubygems'
require 'net/http'
require 'uri'
require 'builder'

endpoint = 'http://localhost:10080/'
soap = 'http://schemas.xmlsoap.org/soap/envelope/'
service =  'http://www.w3.org/2002/ws/databinding/examples/6/05/'
operation = "echoStringElement"

xml = Builder::XmlMarkup.new
xml.Envelope :xmlns => soap do
  xml.Body do
     xml.tag! operation, 'Be like the squirrel!', :xmlns => service
  end
end

module Net
  module HTTPHeader
    def canonical( k )
      return "SOAPAction" if k == 'soapaction'
      k.split(/-/).map {|i| i.capitalize }.join('-')
    end
  end
end

uri = URI.parse(endpoint)
http = Net::HTTP.new(uri.host, uri.port)
#http.set_debug_output $stderr

req_headers= {
  'Content-Type' => 'text/xml; charset=utf-8',
  'SOAPAction' => '"' + service + '#' + operation + '"',
}

req_body = xml.target!
response = http.request_post(uri.path, req_body, req_headers)
puts response.body

Note I followed Sam's example and used XML::Builder to make the SOAP message. I now anticipate bile and vitriol from the apparently friendly, inclusive Ruby community :-)

Technorati Tags: , , ,

Comments { 3 }

  1. expect Star Wars graphics from LRH! er, DHH

  2. Thanks for the tip.

    If your only goal is to change the HTTP header "Soapaction" to "SOAPAction" then you can continue to use SOAP4r . Just be sure to place your Net::HTTPHeader change somewhere in scope.

    I'm using Soap4R 1.5.5 and Ruby 1.8.6 so I had to use this:

    module Net
    module HTTPHeader
    def capitalize(name)
    STDERR.puts "canonical( k )"
    return "SOAPAction" if name == 'soapaction'
    name.split(/-/).map {|s| s.capitalize }.join('-')
    end
    end
    end

  3. Firstly, thank you for the code snippet. Its really nice. In my implementation I have to first pass in authentication username and password before I access any webservice methods. I search accross some documentation to find if there is anyway i can set the basic authentication but did not find answer.
    I would really appreciate if you i can get some help.
    Again my implementation is exactly in the same lines as the one you have specified above except that I need authentication too.

    Thank you