Complex soap_header xml objects for ruby savon gem - ruby

Working on a project with this WSDL: http://developer.ebay.com/webservices/latest/ebaysvc.wsdl
$client = Savon.client(
:wsdl => "http://developer.ebay.com/webservices/latest/ebaysvc.wsdl",
:endpoint => "https://api.sandbox.ebay.com/wsapi?callname=AddItem&siteid=0&version=733& Routing=new",
:headers => { "Content-Type" => "application/soap+xml", "SOAPAction" => "AddItemRequest"},
:namespace => "urn:ebay:apis:eBLBaseComponents",
:soap_header => { CREDENTIALS GO HERE: SEE BELOW }
)
What I need is a complex type xml format. Where the first part of soap_header is RequestCredentials and has several child nodes, and one of those (Credentials) has 3 child nodes... I also need to escape the lower camel case and just use camel case.
The final result with the xml output should look something like:
<urn:RequestCredentials>
<urn:eBayAuthToken>
AUTH TOKEN HERE
</urn:eBayAuthToken>
<urn:Credentials>
<urn:DevId>DEVID HERE</urn:DevId>
ect..... (two more child nodes (AppId, and AuthCert)
</urn:Credentials>
</urn:RequestCredentials>
Here is the error I receive:
14007
Error
SOAP Authentication failed due to missing or invalid security header.
Any ideas on how to correctly format the xml with the savon gem?

Related

How to create SOAP nested headers with SAVON

I would like to generate following soap header with SAVON but cannot really find any proper documentation for it any help would be appreciated.
<SOAP-ENV:Header>
<trp:protocolVersion>4.0</trp:protocolVersion>
<trp:id>*******</trp:id>
<trp:userId>*******</trp:userId>
<trp:service crv:objectType=“SERVICE”>
<crv:memberClass>xxxxxx</crv:memberClass>
<crv:memberCode>xxxxxx</crv:memberCode>
<crv:subsystemCode>xxxxxxxx</crv:subsystemCode>
<crv:serviceCode>xxx</crv:serviceCode>
</trp:service>
</SOAP-ENV:Header>
This is what I have so far, but I am struggling to build the nested objectType in the header
{
"trp:protocolVersion" => 4.0
"trp:id" => id,
"trp:userId" => user_id
"trp:service" => {
'',
:attributes!=> {
'trp:service' => {'objectType' =>'SERVICE'}} },
}

How can I upload files to Redmine via ActiveResource / REST API?

I am trying to batch-upload images to Redmine and link them each to a certain wiki pages.
The docs (Rest_api, Using the REST API with Ruby) mention some aspects, but the examples fail in various ways. I also tried to derive ideas from the source - without success.
Can anyone provide a short example that shows how to upload and link an image from within Ruby?
This is a bit tricky as both attachments and wiki APIs are relatively new, but I have done something similar in the past. Here is a minimal working example using rest-client:
require 'rest_client'
require 'json'
key = '5daf2e447336bad7ed3993a6ebde8310ffa263bf'
upload_url = "http://localhost:3000/uploads.json?key=#{key}"
wiki_url = "http://localhost:3000/projects/some_project/wiki/some_wiki.json?key=#{key}"
img = File.new('/some/image.png')
# First we upload the image to get attachment token
response = RestClient.post(upload_url, img, {
:multipart => true,
:content_type => 'application/octet-stream'
})
token = JSON.parse(response)['upload']['token']
# Redmine will throw validation errors if you do not
# send a wiki content when attaching the image. So
# we just get the current content and send that
wiki_text = JSON.parse(RestClient.get(wiki_url))['wiki_page']['text']
response = RestClient.put(wiki_url, {
:attachments => {
:attachment1 => { # the hash key gets thrown away - name doesn't matter
:token => token,
:filename => 'image.png',
:description => 'Awesome!' # optional
}
},
:wiki_page => {
:text => wiki_text # original wiki text
}
})

Savon: WCF Soap service with wsse auth: AddressFilter mismatch at the EndpointDispatcher

I am trying to create SOAPClient using Savon - rubygem.
Its a WCF soap service with WSSE auth over https. Here is the code that I tried:
require 'savon'
client = Savon::Client.new do
wsdl.document = "https://svc.sxxxxxify.com:8081/ConfSet.svc?wsdl"
config.soap_version = 2
wsse.credentials "aa5#xxasxsaxsh.com", "test123"
end
p client.wsdl.soap_actions
response = client.request :get_user_clients
p response
But I get this error:
http://www.w3.org/2005/08/addressing/soap/fault2012-10-26T06:07:42.247Z2012-10-26T06:12:42.247Zs:Sendera:DestinationUnreachableThe message with To '' cannot be processed at the
receiver, due to an AddressFilter mismatch at the EndpointDispatcher.
Check that the sender and receiver's EndpointAddresses
agree.
.
The message with To '' cannot be processed at the receiver, due to an
AddressFilter mismatch at the EndpointDispatcher. Check that the
sender and receiver's EndpointAddresses agree. (Savon::SOAP::Fault)
Please help me solve this problem
I had the some problem. I've solved the 'To' problem by providing a header entry and a new namespace. The 'Action' header was also necessary though, and I only discovered that after inspecting SoapUI logs. Here is what worked for me:
#service_url = 'https://svc.sxxxxxify.com:8081/ConfSet.svc/service'
#action = 'your_action'
#client = Savon.client(:wsdl => "#{#service_url}?wsdl", :soap_version => 2,
:namespaces => {"xmlns:x" => "http://www.w3.org/2005/08/addressing"},
:soap_header => {"x:To" => #service_url, "x:Action" => "http://tempuri.org/#{#action}"})

Parse WSDL file with SOAP4R

Is there any example of WSDL Parser using SOAP4R? I'm trying to list all operations of WSDL file but I can't figure it out :( Can you post me some tutorial?
Thx
Maybe that isn't answer you want, but I recommend you switch to Savon. For example, your task looks like this snippet (this example taken from github's savon page):
require "savon"
# create a client for your SOAP service
client = Savon::Client.new("http://service.example.com?wsdl")
client.wsdl.soap_actions
# => [:create_user, :get_user, :get_all_users]
# execute a SOAP request to call the "getUser" action
response = client.request(:get_user) do
soap.body = { :id => 1 }
end
response.body
# => { :get_user_response => { :first_name => "The", :last_name => "Hoff" } }

Case problem in SOAP message tag names using savon

I'm using Ruby 1.9.2 with savon 0.9.2 on Windows 7 Professional 64 bit.
I need to call a web SOAP service that requires a security token that I get from a second web SOAP service. The code I use is as follows:
require 'savon'
client = Savon::Client.new "http://some.url?wsdl"
client.wsdl.soap_actions
start_session_response = client.request :start_session do
soap.input = ["StartSession", {:xmlns => "http://some.schema" } ]
soap.body = { :userName => "User", :password => "password" }
end
do_something_response = client.request :do_something do
soap.input = [ "DoSomething", { :xmlns => "http://some.schema"} ]
soap.body = { :securityToken => start_session_response.to_hash[:start_session_response][:security_token] }
end
This results in XML that looks like:
<?xml version="1.0" encoding="utf-8"?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:wsdl="http://some.schema"
xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Body>
<DoSomething xmlns="http://some.schema">
<wsdl:securityToken>
<wsdl:tokenType>sessiontoken</wsdl:tokenType>
<wsdl:token>
.
.
.
</wsdl:token>
</wsdl:securityToken>
</DoSomething>
</env:Body>
</env:Envelope>
Never mind the weird namespace convention (or is that just me) in this XML that is savon doing its thing.
The problem I face is that the tags inside the securitytoken tag all start with a lower case letter where they should be upper case. So <tokenType> and <token> should have been <TokenType> and <Token>.
In my opinion the definition of these tags are all in the WSDL that is used to create the savon client. That definition seems not to be used or used incorrectly.
What can I do to get the correct XML/SOAP message from savon?
For later releases of Savon, you should be able to supply a 'global' option of convert_request_keys_to when you initialize your Savon client:
# In Savon 2
Savon.client wsdl:"http://some.url?wsdl", convert_request_keys_to: :camelcase
According to comments in the source file, it accepts one of :lower_camelcase, :camelcase, :upcase, or :none.
I had a similar problem with Savon and ended up using strings in stead of symbols for my hash keys, you could try something like:
soap.body = { 'TokenType'=> 'some_value', 'Token' => 'some_value' }
Savon uses Gyoku for the conversion of tags I believe. To change the symbol conversion you can insert the following statement:
Gyoku.convert_symbols_to :camelcase # or one of [:none, :lover_camelcase]
hope that helps.

Resources