How to create complex headers using soap4r

102 views
Skip to first unread message

Erik Lindblad

unread,
Jan 2, 2009, 8:50:23 PM1/2/09
to soap4r
Hi

I am writing a blog post on setting SOAP headers, including nested
elements with different namespaces, in different ways using soap4r. I
have managed to get quite a few examples to run using Handler and
SimpleHandler classes but when the header gets a little complex my
code becomes very messy.

Does anyone out there have an easy (or at least clean) solution to
generate the following SOAP header:

<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/
envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-
instance">

<soapenv:Header>
<wsse:Security soapenv:actor="http://manning.com/xmlns/samples/
soasecimpl/cop"
soapenv:mustUnderstand="0"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/
oasis-200401-wss-wssecurity-secext-1.0.xsd">
<wsse:UsernameToken>
<wsse:Username>chap</wsse:Username>
</wsse:UsernameToken>
</wsse:Security>
</soapenv:Header>

<soapenv:Body>
...
</soapenv:Body>
</soapenv:Envelope>

Grateful for any input on this so that I can proceed with the post.
Given the recent activity in soap4r and the adoption rate of WS-*
standards I think there are quite a few people out there who could
benefit from a guide on this.

Kindest regards

Erik

xrs1133

unread,
Jan 15, 2009, 2:33:39 PM1/15/09
to soap4r
Have you made any headway on sending in custom headers.
I am trying to send in this
'<soap:Header>
<MessageHeader xmlns="http://MessageHeader/1.0.0">
<Context>
<Culture xmlns="http://CanonicalModel/1.0.0">en-US</
Culture>
<TimeStamp xmlns="http://CanonicalModel/
1.0.0">2009-01-09T17:44:32.6441748Z</TimeStamp>
<Principal xmlns="http://CanonicalModel/1.0.0">
<SystemUsername>Client</SystemUsername>
<SystemPassword>555555555555555</SystemPassword>
</Principal>
<LineOfBusiness xmlns="CanonicalModel/1.0.0">Handset</
LineOfBusiness>
<Application xmlns="CanonicalModel/1.0.0">PHP</Application>
<Client xmlns="http://CanonicalModel/1.0.0">PhoneDealer</
Client>
<Channel xmlns="http://CanonicalModel/1.0.0">InStore</
Channel>
</Context>
</MessageHeader>
</soap:Header>'

any help would be awesome.

BobiJo

unread,
Jan 23, 2009, 11:53:17 AM1/23/09
to soap4r
I've had the same problem here is how the solution goes (It gets the
job done)
class MyHeaderHandler < SOAP::Header::SimpleHandler
def initialize(val, attr)
@username = attr[:username]
@password = attr[:password]
super(XSD::QName.new(nil, val))
end

def on_simple_outbound
self.mustunderstand = 1
security =SOAP::SOAPElement.new(nil)
security.extraattr['your-attr'] = 'http://url'
timestamp = SOAP::SOAPElement.new('wsu:Timestamp')
timestamp.extraattr['wsu:Id'] = 123
security.add(timestamp)
security
end #outbound
driver.headerhandler << MyHeaderHandler.new('wsse:Security', h)
#add header handlers as many as you need :) create cases for the val
argument ()

How you add stuff to your envelope:

class MyFilterHandler < SOAP::Filter::Handler
def on_outbound(env, opt)
ns = XSD::NS.new({})
ns.assign(something, 'somethingelse')
ns.each_ns do |value,tag|
env.extraattr["xmlns:#{tag}"] = value
end
opt[:generate_explicit_type] = false
opt[:ns] = ns
env
end
end
driver.proxy.filterchain << MyFilterHandler.new
Hope this helps

DanW

unread,
Jan 26, 2009, 5:21:43 AM1/26/09
to soap4r
Hi Erik,


any progress with the blog post tutorial? I can just about follow the
3rd post but a slightly more detailed explanation would be really
useful :)

Kind Regards,
Dan

Erik Lindblad

unread,
Jan 26, 2009, 5:34:46 AM1/26/09
to soa...@googlegroups.com
Hi

The real world are taking some time from that but it is definitely on
the radar. Note that the post will not be a "How to do complex headers
using soap4r" but rather "How to call a SOAP service needing complex
headers without using soap4r". The use case is where you do not have
heavy SOAP interaction, for example one SOAP call to get external data.
More along the lines of a "what happens under the hood when calling a
SOAP service" to demystify the SOAP process a bit. I will post here once
the text is up.

/Erik

DanW skrev:

Chris Songer

unread,
Jan 26, 2009, 2:15:20 PM1/26/09
to soa...@googlegroups.com
Here is how I was able to handle a complex header type. Hope this helps.

require 'soap/header/simplehandler'

n = XSD::NS.new
n.assign("soap", "")

class HeaderHandler < SOAP::Header::SimpleHandler
attr_accessor :value

def initialize(ns,tag)
super(XSD::QName.new(ns, tag))
@value = value
end

def on_simple_outbound
@value
end
End

h =
HeaderHandler.new("http://service.asurion.com/schemas/MessageHeader/1.0.0",
"MessageHeader")
driver.headerhandler << h
h.value = {XSD::QName.new("http://example.com/schemas/MessageHeader/1.0.0",
"Context") => {XSD::QName.new("http://example.com/schemas/
exampleCanonicalModel/1.0.0", "Culture") => "en-US" ,
XSD::QName.new("http://example.com/schemas/ exampleCanonicalModel/1.0.0",
"TimeStamp") => "2009-01-09T17:44:32.6441748Z", XSD::QName.new("http://
example.com/schemas/exampleCanonicalModel/1.0.0", "Principal") =>
{XSD::QName.new("http://example.com/schemas/exampleCanonicalModel/1.0.0","Sy
stemUsername") => "clientname",
XSD::QName.new("http://example.com/schemas/exampleCanonicalModel/1.0.0","Sys
temPassword") => 55555555},
XSD::QName.new("http://example.com/schemas/exampleCanonicalModel/1.0.0",
"LineOfBusiness") => "Handset",
XSD::QName.new("http://example.com/schemas/exampleCanonicalModel/1.0.0",
"Application") => "Aggregator",
XSD::QName.new("http://example.com/schemas/exampleCanonicalModel/1.0.0",
"Client") => "Google",
XSD::QName.new("http://example.com/schemas/exampleCanonicalModel/1.0.0",
"Channel") => "InStore"}}


###################################### Output of header from wiredump

<soap:Header>
<n1:MessageHeader
xmlns:n1="http://example.com/schemas/MessageHeader/1.0.0"
soap:mustUnderstand="0">
<n1:Context
xmlns:n2="http://example.com/schemas/exampleCanonicalModel/1.0.0">
<n2:LineOfBusiness>Handset</n2:LineOfBusiness>
<n2:Client>Google</n2:Client>
<n2:Channel>InStore</n2:Channel>
<n2:Application>Aggregator</n2:Application>
<n2:Principal>
<n2:SystemPassword>55555555</n2:SystemPassword>
<n2:SystemUsername>clientname</n2:SystemUsername>
</n2:Principal>
<n2:TimeStamp>2009-01-09T17:44:32.6441748Z</n2:TimeStamp>
<n2:Culture>en-US</n2:Culture>
</n1:Context>
</n1:MessageHeader>
</soap:Header>

Dalton

unread,
Feb 22, 2009, 4:33:54 PM2/22/09
to soap4r
This is what I've been looking for for the past two days. Thank you.

On Jan 26, 2:15 pm, Chris Songer <cson...@gmail.com> wrote:
> Here is how I was able to handle a complex header type. Hope this helps.
>
> require 'soap/header/simplehandler'
>
> n = XSD::NS.new
> n.assign("soap", "")
>
> class HeaderHandler < SOAP::Header::SimpleHandler
>   attr_accessor :value
>
>   def initialize(ns,tag)
>     super(XSD::QName.new(ns, tag))
>      @value = value
>    end
>
>    def on_simple_outbound
>      @value
>    end
> End
>
> h =
> HeaderHandler.new("http://service.asurion.com/schemas/MessageHeader/1.0.0",
> "MessageHeader")
> driver.headerhandler << h
> h.value = {XSD::QName.new("http://example.com/schemas/MessageHeader/1.0.0",
> "Context") => {XSD::QName.new("http://example.com/schemas/
> exampleCanonicalModel/1.0.0", "Culture") => "en-US" ,
> XSD::QName.new("http://example.com/schemas/exampleCanonicalModel/1.0.0",
> On 1/26/09 4:21 AM, "DanW" <dan.m.w...@gmail.com> wrote:
>
>
>
> > Hi Erik,
>
> > any progress with the blog post tutorial? I can just about follow the
> > 3rd post but a slightly more detailed explanation would be really
> > useful :)
>
> > Kind Regards,
> > Dan
>
> > On Jan 3, 1:50 am, Erik Lindblad <e...@aldm.se> wrote:
> >> Hi
>
> >> I am writing a blog post on setting SOAPheaders, including nested

DanW

unread,
Feb 23, 2009, 4:21:19 AM2/23/09
to soap4r
Just to add to that, I've now written up what I've learnt, but rather
using SOAP4R.

http://dan-webb.co.uk/wordpress/?p=13
Reply all
Reply to author
Forward
0 new messages