How do I add an attribute to a SOAP header with Savon? - ruby

I need to add this attribute (xmlns:wsa="http://www.w3.org/2005/08/addressing") to the soap header, like this:
<env:Header xmlns:wsa="http://www.w3.org/2005/08/addressing">
</env:Header>
How do I do this, using Savon?

I was actually able to make another workaround to the problem in my case, since my endpoint would accept this:
<env:Header>
<wsa:Action xmlns:wsa="http://www.w3.org/2005/08/addressing">value</wsa:Action>
</env:Header>
Investigating the original question, here's the response from the Savon creator:
"hey magne,
looking at the code which creates the header and body tags, it doesn't seem
possible to add any attributes/namespaces without monkey-patching right now:
https://github.com/rubiii/savon/blob/v0.9.7/lib/savon/soap/xml.rb#L151
if you still need this feature, please open a ticket and i'll see what i can do:
https://github.com/rubiii/savon/issues
i'm currently very involved in taking a new approach to improve the library,
so i'm not sure when i'll be able to solve your problem. but ... i hacked together
a small monkey-patch that should help until this feature is implemented:
https://gist.github.com/1698636
cheers,
daniel"

You can add your own namespace to the request like this:
resp = client.request :soap_action do
soap.namespace['xmlns:wsa'] = 'http://www.w3.org/2005/08/addressing'
end

foo = client.request do
soap.header['xmlns:wsa'] = 'http://www.w3.org/2005/08/addressing'
end

Related

Render a view's output later via a delayed_job

If I render html I get html to the browser which works great. However, how can I get a route's response (the html) when being called in a module or class.
I need to do this because I'm sending documents to DocRaptor and rather than store the markup/html in a db column I would like to instead store record IDs and create the markup when the job executes.
A possible solution is using Ruby's HTTP library, Httparty or wget or something and open up the route and use the response.body. Before doing so I thought I'd ask around.
Thanks!
-- Update --
Here's something like what I ended up going with:
Quick tip - in case anyone does this and need their helper methods you need to extend AV with ApplicationHelper:
Here's something like what I ended up doing:
av = ActionView::Base.new()
av.view_paths = ActionController::Base.view_paths
av.extend ApplicationHelper #or any other helpers your template may need
body = av.render(:template => "orders/receipt.html.erb",:locals => {:order => order})
Link:
http://www.rigelgroupllc.com/blog/2011/09/22/render-rails3-views-outside-of-your-controllers/
check this question out, it contains the code probably want in an answer:
Rails 3 > Rendering views in rake task

Refactor my ruby snippet so it doesn't look like C anymore: method(method(param))

I have a class which uses a connection object to send the request data created by a request_builder object.
The code looks like this:
connection.send_request(request_builder.build_request(customer))
This in turn is called by
build_report(customer, connection.send_request(request_builder.build_request(customer)))
Ugly! Any ideas on how to make it more expressive? Usually in ruby and OOP we chain objects like this: "string".make_it_bigger.flash_it.send
It's code, that how it looks. But you can make yourself a favour by not trying to cram everything together on one line:
request = request_builder.build_request(customer)
response = connection.send_request(request)
report = build_report(customer, response)
if you told us more about your code base we might be able to suggest something else, but you don't give us very much to go on. What does the request_builder object do? Does connection.send_request(...) return a response? Why does a report need a customer and a response (assuming that's what is returned by connection.send_request(...)), and so on.
build_report(customer, request_builder.build_request(customer).send_over(connection))

Passing a blank XSD::QName using soap4r

I have overridden the SimpleHandler to pass a username and password using soap4r. the problem is that I am forced to give a QName, and this is causing the result to fail because it's not in the right format.
What soap4r is adding is something like this (the "ns1" things are dummy values):
<env:Header>
<n1:ns1 env:mustUnderstand="0"
xmlns:n1="ns1">
<n1:Username>someuser</n1:Username>
<n1:Password>topsecret</n1:Password>
</n1:ns1>
</env:Header>
What it needs to be is this:
<env:Header>
<n1:Username>someuser</n1:Username>
<n1:Password>topsecret</n1:Password>
</env:Header>
How can I NOT pass in a containing name?
Looks like you need to make some changes to soap4r: http://dev.ctor.org/soap4r/browser/branches/1_5/lib/soap/header/handler.rb
If the service isn't all that complicated you could try Handsoap
https://github.com/unwire/handsoap/wiki/authentication#WS-Security
Soap4R is quite picky about overriding headers. In your situation, you'll need to add two "flat" handlers (one for Username, and another for Password) instead of a single one with both.

Generate an HTTP response in Ruby

I'm working on an application that reaches out to a web service. I'd like to develop a proxy class that returns a fake response from the service, so I don't have to constantly be hitting it with requests while I'm developing/testing other parts of the app.
My application is expecting a response generated via Net::HTTP.
response = Net::HTTP.get(URI.parse('http://foo.com'))
case response
when Net::HTTPOK
# do something fun
when Net::HTTPUnauthorized
# you get the idea
How can I manufacture a response object, give it all the right headers, return a body string, etc?
response = ProxyClass.response_object
case response
when Net::HTTPOk
# my app doesn't know it's being lied to
Thanks.
It's actually not that hard to roll your own fake responses directly with Net::HTTP. Here's a simple 200 OK with a cookie header:
def fake_response
net_http_resp = Net::HTTPResponse.new(1.0, 200, "OK")
net_http_resp.add_field 'Set-Cookie', 'Monster'
RestClient::Response.create("Body goes here", net_http_resp, nil)
end
Since few of us are using raw Net::HTTP anymore, the (optional) last line wraps it up as a RestClient::Response, which can then be stubbed into RestClient:
stub(RestClient).post(anything) { fake_response }
I would start with FakeWeb and see if that meets your needs. If it doesn't you can probably gut whatever you need out of the internals and create your own solution.
I know this post is old, but instead of FakeWeb which seems to be largely dead, try webmock. It seems to be more full-featured and very active.
I would look into a mocking library like mocha.
Then you should be able to setup a mock object to help test:
Then following example is from Tim Stephenson's RaddOnline blog, which also includes a more complete tutorial:
def setup
#http_mock = mock('Net::HTTPResponse')
#http_mock .stubs(:code => '200', :message => "OK", :content_type => > "text/html", :body => '<title>Test</title><body>Body of the page</body>')
end
For testing a web service client, we use Sinatra, a lovely little lightweight web framework that lets you get something up and running very quickly and easily. Check out the home page; it has an entire Hello World app in 5 lines of code, and two commands to install and run the whole thing.
I ended up using a Struct.
FakeHttpResponse = Struct.new(:status, :body)
http = FakeHttpResponse.new('success', 'body goes here')
http['status'] # = 'success'
http.body # = 'body goes here'
The drawback is that .status and ['body'] are also valid, but I don't think that matters much.
I would either use FakeWeb as mentioned above, or have my rake test task start a Webrick instance to a little sinatra app which mocks the various test responses you're hoping to see.
You could look into using Rack for this which should allow you to do everything you need.

How do I add a name.value to the header when generating a soap message from ruby with soap4r

I've created a driver from wsdl
When I invoke my request, I would like the header to contain an element, i.e, I want to see something like the following:
REPLACE_WITH_ACTUAL
blah blah blah
However, looking around, everyone talks about subclassing SOAP::Header::SimpleHandler and then injecting an instance into the driver.headerhandler
However, if I do that, then I end up with a nested header, i.e,
REPLACE_WITH_ACTUAL
So there must be a way to just add an element to the existing headerhandler so I can do something like
driver.headerhandler.AddElement("session", "123")
but I can't find any way to do that. I also tried things like
driver.headerhandler["session"]="123" and other such tricks, but I can't find any way to make this work.
Looking at driver.headerhandler.methods, I cannot see any obvious mechanism.
Would really appreciate a pointer to how to to this.
Well, a colleague in my team solved the problem above after looking at some of the typical examples that I had previously found including the one at http://dev.ctor.org/soap4r/browser/trunk/sample/soapheader/authheader/client2.rb
Turns out that the trivial (sigh) solution is to replace
def on_simple_outbound
if #sessionid
{ "sessionid" => #sessionid }
end
end
with
def on_simple_outbound
if #sessionid
#sessionid
end
end
Now, if you just name the header "session" (in the QName creation), you get the unnested header, exactly what I wanted.
I thought I'd paste my solution to my own problem on the assumption that others might be running into the same problem.

Resources