savonrb / savon Goto Github PK
View Code? Open in Web Editor NEWHeavy metal SOAP client
Home Page: https://www.savonrb.com
License: MIT License
Heavy metal SOAP client
Home Page: https://www.savonrb.com
License: MIT License
given a wsdl that has a location as follows (scrubbed)
<soap:address location="https://somthing.something.com/incident.do?SOAP"/>
a client instance wsdl.soap_endpoint will return the correct value however when you make a soap call, savon is trimming off the ?SOAP. I was getting odd 302 errors and when I ran it through Charles it showed the trimmed URI
Hi,
I am not an expert in soap but I am trying to specify some body to be something like
5 and concatenate that to the result of Hash.to_soap_xml
A sample of the generated message is like this
<env:Envelope xmlns:wsdl="http://someplace.com/" xsi="http://www.w3.org/2001/XMLSchema-instance" xs="http://www.w3.org/2001/XMLSchema" apis="http://someplace.com/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">env:Bodywsdl:find5Something/wsdl:find/env:Body/env:Envelope
but web service I use seems to complain with the a parsing error
S:Serverjavax.xml.bind.UnmarshalExceptionMessage: http://www.w3.org/TR/1999/REC-xml-names-19990114#AttributePrefixUnbound?id&xsi:type&xsi]<ns2:exception xmlns:ns2="http://jax-ws.dev.java.net/" class="javax.xml.ws.WebServiceException" note="To disable this feature, set com.sun.xml.ws.fault.SOAPFaultBuilder.disableCaptureStackTrace system property to false">javax.xml.bind.UnmarshalException
Any idea what I am doing wrong or if this is unsupported or a bug?
Thanks
Manu
I'm trying to set the header of the soap object, but it doesn't appear to be working. Am I doing something wrong?
thanks in advance,
mike
client = Savon::Client.new wsdl
client.test_credentials do |soap|
soap.header = {:UserCredentials=>{:UserName=>user, :Password=>pass}}
end
D, [2009-12-06T15:38:20.595883 #20511] DEBUG -- : Retrieving WSDL from: https://www.demo.reprintsdesk.com/webservice/main.asmx?wsdl
warning: peer certificate won't be verified in this SSL session
D, [2009-12-06T15:38:21.923520 #20511] DEBUG -- : SOAP request: https://www.demo.reprintsdesk.com/webservice/main.asmx?wsdl
D, [2009-12-06T15:38:21.923643 #20511] DEBUG -- : SOAPAction: Test_Credentials, Content-Type: text/xml
D, [2009-12-06T15:38:21.924137 #20511] DEBUG -- : <env:Envelope xmlns:wsdl="http://reprintsdesk.com/webservices/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">env:Header/env:Headerenv:Bodywsdl:Test_Credentials/wsdl:Test_Credentials/env:Body/env:Envelope
D, [2009-12-06T15:38:22.682205 #20511] DEBUG -- : SOAP response (status 500):
D, [2009-12-06T15:38:22.683333 #20511] DEBUG -- : <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">soap:Bodysoap:Faultsoap:ClientServer did not recognize the value of HTTP Header SOAPAction: Test_Credentials./soap:Fault/soap:Body/soap:Envelope
NoMethodError: undefined method header=' for #<Net::HTTPInternalServerError:0x10159f4f0> from (irb):7 from /Library/Ruby/Gems/1.8/gems/savon-0.5.3/lib/savon/client.rb:81:in
call'
from /Library/Ruby/Gems/1.8/gems/savon-0.5.3/lib/savon/client.rb:81:in dispatch' from /Library/Ruby/Gems/1.8/gems/savon-0.5.3/lib/savon/client.rb:73:in
method_missing'
from (irb):6
savon expects main operation tags to have a namespace, i.e. "wsdl:operation". seems like this is not always the case. going to fix this problem asap.
reference: http://github.com/rubiii/savon/issues/closed#issue/4
It seems that by default you are camel casing the following way:
user_type_id to userTypeId
but it seems I see people using userTypeID instead for casing. I think more people tends to leave ID uppercase ...
Either a work around or different notation would though.. though it is easy to use symbol :userTypeID but requires more code now to manage the mapping at time....
First I have to say that this gem has just saved my day! I was using unwire/handsoap, but just couldn't get what I needed. Great job!
I need to define a custom timeout for each SOAP request. Is that possible with savon?
Net::HTTP has the read_timeout function, but I don't know how can I define it within the gem.
Thanks!
I'm trying to authenticate with Savon and WSSE, moving away from soap4r. My soap4r auth header code was this.
class WsseAuthHeader < SOAP::Header::SimpleHandler NAMESPACE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd' USERNAME = 'x' PASSWORD = 'y' def initialize() super(XSD::QName.new(NAMESPACE, 'Security')) end def on_simple_outbound {"UsernameToken" => {"Username" => USERNAME, "Password" => PASSWORD}} end end
In Savon, I'm setting these values
Savon::WSSE.username = "x" Savon::WSSE.password = "y"
But I get an error InvalidSecurityToken fault.
An invalid security token was provided; WSE547: An invalid Created element was found. WSE063: The timestamp 2010-01-27T17:13:15 in the message is not valid. It must be in this UTC format: yyyy-MM-ddTHH:mm:ssZ.
Have messed about scouring the issues, but can't find a way passed this. Any suggestions welcome.
T
The API i'm working with requires me to set the id field inside of a tag in the body. So it needs to look something like this:
Is there a way to do this in the hash i'm passing in, or am I going to have to build the body as an XML doc and pass that in (suboptimal).
thanks!
mike
After creating a client like this:
client = Savon::Client.new "http://<IP_ADDRESS>/path?wsdl"
when I try to run some SOAP action the referred SocketError exception is raised. The problem is that looking in the debug messages I saw it's is using a NAME instead the IP_ADDRESS I used to create the client, like this:
DEBUG -- : SOAP request: http://<NAME>/path
And worst, that NAME even resolves as the reverse address of the IP address.
Is it possible to disable this behavior in the client and use the IP address for the SOAP request?
I wanted to encapsulate some common logic into a helper method and use the 'send' method to actually make the call to the Savon client (as below). It works for a soap action called 'search' but it does not work for one called 'load'. It turns out 'load' is a private method and 'send' is attempting to call it.
def soapcall(client, method_name, arg)
response = client.send method_name, nil do |soap|
soap.namespaces['xmlns:ns1'] = "http://services.foo.com/v1"
soap.body = {
'arg0' => arg
}
end
response.to_hash[(method_name.to_s+"_response").to_sym][:return]
end
Hey there,
Anyone tried to create a soap server with savon? Is it possible? If so, anyone post any notes? Ideally, I'd like to do something with Apache_cxf. Your thoughts?
Cheers.
Hey, I was trying to test this out with the CampaignMonitor API. Unfortunately the api uses a format where the soap command contain periods (User.GetClients, Campaign.GetLists) etc.
Is there any way to get around this? Otherwise, very cool library.
I am not sure if I am doing something wrong or missing something:
but the following
response = client.search_jobs do |soap, wsse|
soap.header = "<AuthHeader xmlns="http://www.hiredesk.net/WebServices/DataExchangeServices/\">" +
{:sCompanyShortName => 'com' ,:sUserName => 'user' , :sPassword => 'pass'}.to_soap_xml +
""
soap.namespaces['xmlns:xsi'] = "http://www.w3.org/2001/XMLSchema-instance"
soap.namespaces['xmlns:xs'] = "http://www.w3.org/2001/XMLSchema"
soap.namespaces['xmlns:wsdl'] = client.wsdl.namespace_uri
soap.body = {:searchCriteria => "<HDCommand>\x0a <SearchJobs>\x0a <AddedAfter>2010-01-01</AddedAfter>\x0a </SearchJobs>\x0a </HDCommand>"}
end
generate this payload
<env:Envelope xmlns:wsdl="http://www.hiredesk.net/WebServices/DataExchangeServices/" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">env:Headeruserpasscomp/env:Headerenv:Bodywsdl:SearchJobs<HDCommand>
<SearchJobs>
<AddedAfter>2010-01-01</AddedAfter>
</SearchJobs>
</HDCommand>/wsdl:SearchJobs/env:Body/env:Envelope
but the webservice on the other end does not like unless I add the following in front of the searchCriteria
wsdl:searchCriteria
So is there a way to do that in Savon automatically? Or Am I missing something in the namespace declaration? Not sure why I have to add wsdl to that searchCriteria tag..
If a response body has the following structure:
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope ...>
<soapenv:Body>
<ns1:getIssueResponse...>
<getIssueReturn href="#id0"/>
</ns1:getIssueResponse>
<multiRef...>
...
</multiRef...>
<multiRef...>
...
</multiRef...>
</soapenv:Body>
</soapenv:Envelope>
then Response.to_hash always returns one child element only, since it only matches the first key. Furthermore, if the first key happens to be multiRef, find_regexp returns an Array. Calling map_soap_response on the Array fails, since that method does not exist.
This commit broke my code:
http://github.com/rubiii/savon/commit/64a78c00760c123b65a0528c4d67772f398d368f#comment_47850
response = client.get_clients do |soap|
soap.action = "http://api.createsend.com/api/User.GetClients"
soap.input = "User.GetClients"
soap.namespace = "http://api.createsend.com/api/"
soap.body = { "wsdl:ApiKey" => token }
end
Used to return results, now gets an error trying to call 'map' on a string
If no header ist set, then no header should be sent, even not an empty <Header> </Header>. I do actually have the case that one SOAP Server handles this as a bad request.
I am working with a webservice where it appears the only way to get it to work is if I pass the WSSE password element as:
<wsse:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">myplaintextpass/wsse:Password
But, Savon produces this:
wsse:Passwordmyplaintextpass/wsse:Password
I don't see anyway to set an attribute for the WSSE password in Savon. I have tinkered with the code to see if I may force it in there, but that is not proving obvious. The reason is that the WSSE uses the wsse:Password format so my skills with Builder are not getting me to where I need to be. The code is from line 96 in lib/wsse.rb:
xml.wsse :Password, password_node
If I had:
xml.Password password_mode
That I would know how to do it. Am I missing something in the API documents, or an obvious way to do this?
I am trying to connect to a service that doesn't exist (for example: IP address with no host) but from what I can tell Savon::Connnect.new doesn't raise an HTTP error if the target host cannot be connected to.
I am still now 100% grokking the savon code so I am not sure if I need to set something or not.
I think you have a similar issue with arrays in SOAP responses as happened in PHP. This was fixed by them adding the option SOAP_SINGLE_ELEMENT_ARRAYS. You can find an outline of the problem here:
http://www.dotvoid.com/2008/10/soap-structures-in-php/
Basically, arrays returned with only one entry are not being returned from .to_hash as arrays.
Here's an example response from each:
[:get_urgent_info_result,
{:array_of_evs1_urgent_info=>
{:evs1_urgent_info=>
{:information=>"MAXIMUM OCCUPANCY OF THE UNIT CANNOT BE EXCEEDED (ADULTS, CHILDREN AND INFANTS COUNT ALIKE. ADDITIONAL PEOPLE CANNOT BE ACCOMODATED IF THEY TURN UP. **NO POOL BAR, BARS OR RESTAURANTS ON SITE BUT PLENTY OF THEM NEARBY.**MEMBERS MUST CONTACT RESORT IF ARRIVING OUTSIDE RECEPTION HOURS**", :expiry_date=>"20701231", :effective_date=>"20021022"
}
}
}
]
[:xmlns, "urn:http://ws.rciholidaynetwork.co.uk/BookingEngine/BookingEngine"]
[:get_urgent_info_result,
{:array_of_evs1_urgent_info=>
{:evs1_urgent_info=>
[
{:information=>"RESORT IS PARTICULARLY SUITABLE FOR FRENCH, ITALIANS, AND RUSSIANS.",
:expiry_date=>"99991231", :effective_date=>"20020819"
},
{:information=>"RESORT´S REFUNDABLE DEPOSIT CHARGE IS 100EUROS (CREDIT CARD OR CASH IS ACCEPTED)
THE SWIMMING POOL IS HEATED FROM NOVEMBER TO APRIL DURING THE YEAR.",
:expiry_date=>"20701231", :effective_date=>"20011004"
}
]
}
}
]
[:xmlns, "urn:http://ws.rciholidaynetwork.co.uk/BookingEngine/BookingEngine"]
Is there a good example for using a soap service that doesn't come with a WSDL?
I'm trying to connect to http://www.communigate.com/Communigatepro/HTTP.html#CLI which doesn't come with a wsdl.
Thanks,
-Joe
Hi -- I'm trying to use Savon with SalesForce, but am getting the following error when I try to do anything with it:
SocketError: getaddrinfo: nodename nor servname provided, or not known
Is there anything I can do to get around this?
I don't know too much about SOAP, but from looking at similar problems, I guess this is something to do with an endpoint? Can I set that myself to get around this?
Cheers,
Doug.
My requests have been broken by 0.7.6, rolling back to 0.7.5 fixes the issue. I think it is probably caused by the fix for issue #41. I have to send XML inside a soap field and it is getting escaped which the system at the other end (Which I have no control over) cannot read it.
Here an excerpt from a soap request as sent by 0.7.6 (Captured by wireshark) - BROKEN
<wsdl:MsgXML><![CDATA[<?xml version="1.0" encoding="utf-8"?><COMMAND><Parameters><FieldName="OUTPUT"
And here is the same XML as sent by 0.7.5 - WORKING
<wsdl:MsgXML><![CDATA[<?xml version="1.0" encoding="utf-8"?><COMMAND><Parameters><FieldName="OUTPUT"
Maybe we need to be able to set a setting to tell Savon to escape or not?
My problem is that i need to put some attributes on the "root" element within the SOAP body, so I need something that looks like:
env:Body
<wsdl:someRequest attr1="val1" attr2="val2">
...
/wsdl:someRequest
/env:Body
Right now the savon api only allows a single element tag name assigned to the input instance variable of the soap object, as in:
response = @savon_client.some_request! do |req|
req.namespace = @namespace
req.action = "someRequest"
req.input = "someRequest"
end
Seems like the most elegant fix might be to expose a little more of the underlying Builder::XmlMarkup object for those who require more flexibility than a simple hash can provide.
Please add support for and document how to use Savon with HTTP basic auth.
Should savon cares about the body of a 401 status response? I believe the parsing exception [1] is preventing the client to authenticate, but the body content is completely useless here, right?
Best,
Marcos Hack.
Hi,
Would it be possible to add support for using WSDL stored locally as a file?
Example:
Savon::Client.new "http://www.domain.tld/SomeWebService.asmx?wsdl"
Savon::Client.new "file:///path/to/SomeWebService.wsdl"
Then you don't have to download large WSDL from web-service (at the moment, I have to fetch 2.3 MB of data on each new session).
Thanks for this alternative to SOAP4R.
I am having a problem accessing my web service.
I am hitting a Microsoft Dynamics AX server (not exposed to internet).
I am getting the following message in my response:
OperationFormatter encountered an invalid Message body.
Expected to find node type 'Element' with name 'GeneralJournalServiceCreateRequest'
and namespace 'http://schemas.microsoft.com/dynamics/2008/01/services'.
Found node type 'Element' with name 'wsdl:create'
and namespace 'http://schemas.microsoft.com/dynamics/2008/01/services'
Here is snippet from the WSDL:
<wsdl:portType name="GeneralJournalService">
<wsdl:operation name="create">
<wsdl:input wsaw:Action="http://schemas.microsoft.com/dynamics/2008/01/services/GeneralJournalService/create"
name="GeneralJournalServiceCreateRequest"
message="tns:GeneralJournalServiceCreateRequest" />
<wsdl:output wsaw:Action="http://schemas.microsoft.com/dynamics/2008/01/services/GeneralJournal>Service/createResponse"
name="GeneralJournalServiceCreateResponse"
message="tns:GeneralJournalServiceCreateResponse" />
<wsdl:fault wsaw:Action="http://schemas.microsoft.com/dynamics/2008/01/services/GeneralJournal>Service/createAifFaultFault"
name="AifFaultFault"
message="tns:GeneralJournalService_create_AifFaultFault_FaultMessage" />
</wsdl:operation>
</wsdl:portType>
In the XML I am sending, I don't see "Create" by itself.
Here is the XML I am sending:
Looking at your logging, I see the following in the SOAPAction:
SOAPAction: http://schemas.microsoft.com/dynamics/2008/01/services/GeneralJournalService/create, Content-Type: text/xml;charset=UTF-8
<env:Envelope xmlns:wsdl="http://schemas.microsoft.com/dynamics/2008/01/services" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
env:Body
wsdl:create
/wsdl:create
/env:Body
/env:Envelope
I think that if this SOAPAction had "GeneralJournalServiceCreateRequest"
instead of "wsdl:create", the call would work.
I played with savon/lib/savon/soap.rb input_array method,
but could not override the behavior successfully.
I am on:
Windows XP
Ruby 1.8.6
Savon 0.7.5 (with calamitas NTLM authentication modification)
I would be happy to post more information if required.
Thanks
I've done the following:
sudo gem update rails
sudo gem install savon
rails dummy
cd dummy
script/console
On the console I tried the following:
require 'savon'
client = Savon::Client.new('http://demo.sympa.org/sympa/wsdl')
response = client.login{|soap| soap.body = {'email'=>'[email protected]', 'pwd' => 'my_password'}}
I got the following error:
Retrieving WSDL from: http://demo.sympa.org/sympa/wsdl
NoMethodError: undefined method `ssl?' for #<URI::Generic:0xa6e74a4 URL:>
from /usr/local/lib/ruby/gems/1.8/gems/savon-0.7.2/lib/savon/request.rb:91:in `soap'
from /usr/local/lib/ruby/gems/1.8/gems/savon-0.7.2/lib/savon/client.rb:36:in `method_missing'
Hey! Thanks for your work!
Ive a question, as I see this "gem" is useful with small soap, for biggest like ebay (http://developer.ebay.com/webservices/latest/eBaySvc.wsdl) each request require much time.
I see correctly or there is some thing that I missing?
This is less of a issue, but more a help!
I'm trying to connect to a SOAP, but I always get a:
"Moved Permanently (301): Redirecting to Login..."
I'm loading the wsdl, and I can access client.wsdl.soap_operations and see my operations there, so I assume I'm calling it wrong.
This is my code:
client = Savon::Client.new 'http://10.0.5.68/cmi?wsdl'
response = client.reset { |soap| soap.body = { :sid => '0620628830'} }
Sorry to disturb you, but I would really appreciate your help.
Having installed the Savon 0.6.7 gem and trying to require I am getting:
require 'rubygems'
=> false
require 'savon'
NameError: uninitialized constant Savon
from ./savon.rb:4
from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:ingem_original_require' from /Library/Ruby/Site/1.8/rubygems/custom_require.rb:31:in
require'
from (irb):2
I'm not convinced this is an issue with Savon, but rather my struggling with the Soap in general. Maybe you will have a suggestion though.
I set up the XML and made the request using Savon. The request returned a SOAPFault, server error 500 with an error message "Object reference not set to an instance of an object." I had seen this before when i was missing required fields in the XML, so I copy and pasted the entire soap envelope into SoapUI and made the request. it worked perfectly from SoapUI though. Why would the request work in SoapUI but not through Savon? What other variables are there besides the contents of the envelope that I can use to debug this?
thanks in advance
mike
this does not work
client = Savon::Client.new "http://example.com"
response = client.get_programs! do |soap|
soap.namespace = "http://example.com"
soap.body = { :username => "user", :password => "somePass21&" , :campaignid => 123 }
end
this does
xml = Builder::XmlMarkup.new
xml.username "user"
xml.password "somePass21&"
xml.campaignid 123
client = Savon::Client.new "http://example.com"
response = client.get_programs! do |soap|
soap.namespace = "http://example.com"
soap.body = xml.target!
end
(reported by luqman)
If the WSDL meets the "invalid" criteria when loading, Savon attempts to call an "invalid!" method that does not appear to be defined in the current gem (0.5.2).
require 'savon'
proxy = Savon::Client.new "https://test-api.geotrust.com/webtrust/query.jws?WSDL"
proxy.wsdl.soap_actions
D, [2009-11-30T15:58:46.389373 #40297] DEBUG -- : Retrieving WSDL from: https://test-api.geotrust.com/webtrust/query.jws?WSDL
warning: peer certificate won't be verified in this SSL session
NoMethodError: undefined method `invalid!' for #<Savon::WSDL:0x102319540>
from /Library/Ruby/Gems/1.8/gems/savon-0.5.2/lib/savon/wsdl.rb:44:in `wsdl_response'
Hi, Thanks for the help earlier. I'm trying to figure out how to get the soap body to handle duplicate elements. like.
<createAccount>
<param>[email protected]</param>
<key>TextMailbox</key>
<param>
<subKey key="RealName">John Doe</subKey>
<subKey key="Password">soappass</subKey>
</param>
</createAccount>
I find it's difficult to get duplicate param's inserted since it's a hash. Should I do this manually?
-Joe
Hello again, I need to respect the given params order in the soap.body function, but savon seems to order the params alphabetical.
For instance if I assign these values:
soap.body = { :patientID => params[:id], :careTakerID => current_user.id }
the soap envelope will be
env:Body
wsdl:cancelAlarm
2
1
/wsdl:cancelAlarm
/env:Body
I think that it is a problem with the @body.to_soap_xml function. Is it possible to define the order of the params?
Thanks!
Ahoi,
please set utf-8 as default contenttype. Otherwise our SOAP-Server will choose iso-8859-1 for response... :-(
Gesundheit!
The client constructor indicates you can pass in SSL client auth options, how does this work.. I followed it in Request.new, but on the :proxy symbol is being accessed.. ?
Sorry for the vague wording but I am a newbie to SOAP so not sure about the terminology. What I need is
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:lb="snipped">
<soap:Header/>
<soap:Body>
<lb:Authenticate>
<lb:UserName>x</lb:UserName>
<lb:Password>x</lb:Password>
</lb:Authenticate>
</soap:Body>
</soap:Envelope>
but when I use savon I get
<env:Envelope xmlns:wsdl="snipped" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
<env:Header>
</env:Header>
<env:Body>
<wsdl:Authenticate>
<password>x</password>
<userName>x</userName>
</wsdl:Authenticate>
</env:Body>
</env:Envelope>
So I need to get rid of the "Env" stuff and replace the "wsdl" with "lb". Is this possible, if so what do I have to do?
Cheers
RJ
I cobbled some code together (as per http://wiki.github.com/rubiii/savon/wsse):
result = @driver.get(params) {|soap, wsse| wsse.username = @wsse.username; wsse.password = @wsse.password; wsse.digest= @wsse.digest}
for which I get:
$client.webshop_get(:ticket => 0)
NoMethodError: undefined method digest' for #<Savon::WSSE:0xb74413c8> from ./modules/adapter.rb:53:in
webshop_get'
from /var/lib/gems/1.8/gems/savon-0.7.1/lib/savon/client.rb:79:in yield_objects' from /var/lib/gems/1.8/gems/savon-0.7.1/lib/savon/client.rb:69:in
setup_objects'
from /var/lib/gems/1.8/gems/savon-0.7.1/lib/savon/client.rb:35:in method_missing' from ./modules/adapter.rb:53:in
webshop_get'
from (irb):2
Not sure what I'm doing wrong. Ideally, I'd like to assign WSSE data when I initialize the savon client, but see no direct way to attach such information on setup. I need that because some operations must be done within a per-user permission context, so globally setting Savon::WSSE.x=y does not really help, and it seems best to simply attach it to the client itself.
Your thoughts/questions?
>> response = client.login do |soap| ?> soap.body = { ?> "wsdl:username" => "my_username", ?> "wsdl:password" => "my_password" >> } >> end SOAP request: https://api.verticalresponse.com/1.0/VRAPI SOAPAction: VR/API/1_0#login, Content-Type: text/xml my_usernamemy_password SOAP response (status 500): SOAP-ENV:ClientSOAPAction shall match 'uri#method' if present (got 'VR/API/1_0#login', expected 'http://api.verticalresponse.com/1.0/VRAPI#login' Savon::SOAPFault: (SOAP-ENV:Client) SOAPAction shall match 'uri#method' if present (got 'VR/API/1_0#login', expected 'http://api.verticalresponse.com/1.0/VRAPI#login' from /usr/local/ruby-enterprise/lib/ruby/gems/1.8/gems/savon-0.7.1/lib/savon/response.rb:64:in `handle_soap_fault' from /usr/local/ruby-enterprise/lib/ruby/gems/1.8/gems/savon-0.7.1/lib/savon/response.rb:25:in `initialize' from /usr/local/ruby-enterprise/lib/ruby/gems/1.8/gems/savon-0.7.1/lib/savon/client.rb:36:in `new' from /usr/local/ruby-enterprise/lib/ruby/gems/1.8/gems/savon-0.7.1/lib/savon/client.rb:36:in `method_missing' from (irb):61
Hi, rubiii
Thank you for a cool library. I was trying to see if we could use it and ran into a stumbling block. I'm trying to access a SOAP service i don't control. One of the actions is called ProcessMessage. I follow example and generate a SOAP request, but I get an error back saying that the action doesn't exist. I traced the problem to the way the body of the envelope is generated.
<env:Envelope ... ">
<env:Header>
<wsse:Security ... ">
<wsse:UsernameToken ...">
<wsse:Username>USUSER</wsse:Username>
<wsse:Nonce>658e702d5feff1777a6c741847239eb5d6d86e48</wsse:Nonce>
<wsu:Created>2010-02-18T02:05:25Z</wsu:Created>
<wsse:Password ... >password</wsse:Password>
</wsse:UsernameToken>
</wsse:Security>
</env:Header>
<env:Body>
<wsdl:ProcessMessage>
<payload>
......
</payload>
</wsdl:ProcessMessage>
</env:Body>
</env:Envelope>
That ProcessMessage tag should be :
<ProcessMessage xmlns="http://www.starstandards.org/webservices/2005/10/transport">
That's what it is when it is generated by the sample java app, and it works. That tag is the only difference between what my ruby app generates and the sample java app. Is there any way to get rid of the "wsdl:" namesaplce in front of that one tag and add an attribute like that. Barring that, is there a way force the action not to be generated from the name of the soap action called, but be passed as s tring like the rest of the body?
Here is my code.
require 'rubygems'
require 'savon'
client = Savon::Client.new "https://myservice?wsdl"
response = client.process_message! do | soap, wsse |
wsse.username = "USER"
wsse.password = "password"
soap.namespace = "http://www.starstandards.org/webservices/2005/10/transport" #makes no difference
soap.action = "ProcessMessage" #makes no difference in the final xml output
soap.input = "ProcessMessage" #makes no difference in the final xml output
#my body at this point is jsut one big xml string
soap.body = "<payload>...</payload>"
# putting <ProccessMessage> tag here doesn't help as it just creates a duplicate tag in the body, since Savon keeps interjecting <wsdl:ProcessMessage> tag.
end
Thank you
P.S.:
I would really appreciate any pointers. I like the simplicity of savon and I don't wont to be dragged into soap4r, (handsoap doesn't support wsse, or at least I couldn't find y indication of that)
(previously on savon: "HTTP Basic Auth" :)
Is there HTTP Digest Authentication support in Savon?
I'm trying to pass an array, so I need to set a soapenc:arrayType attribute - i.e. the XML needs to look like
<level_one_tag_ids soapenc:arrayType="xsd:int[]">
<level_one_tag_id>143</level_one_tag_id>
<level_one_tag_id>118</level_one_tag_id>
</level_one_tag_ids>
I'm trying to find a way to do this with passing a hash rather than raw XML, but I can't seem to figure out how to set the attribute on the level_one_tag_ids element - I can nest, but I can't set the soapenc. Am I missing the syntax for this, or is this not possible?
Thanks!
I have researched and searched for solution. I get this error when I deploy on the production server glassfish:
MissingSourceFile (no such file to load -- savon):
/usr/src/glassfish/domains/domain1/generated/jsp/j2ee-modules/Locator/loader/META-INF/jruby.home/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in require' /usr/src/glassfish/domains/domain1/generated/jsp/j2ee-modules/Locator/loader/META-INF/jruby.home/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in
require'
etc etc.
It works fine on my windows development machine.
I am hoping somebody can help me, as countless hours have gone!
cheers
David
I am trying to connect to a service that doesn't exist (for example: IP address with no host) but from what I can tell Savon::Connnect.new doesn't raise an HTTP error if the target host cannot be connected to.
I am still now 100% grokking the savon code so I am not sure if I need to set something or not.
I found the line, to fix it in, it's on
lib/savon/wsdl_stream.rb line 35
@section = nil unless @namespaces[namespace] == "http://schemas.xmlsoap.org/wsdl/soap/"
replace that line with
@section = nil unless @namespaces[namespace].start_with? "http://schemas.xmlsoap.org/wsdl/soap"
that will allow the namespace to be "http://schemas.xmlsoap.org/wsdl/soap12/"
I'm having a problem using Savon with a wsdl service provided by Telnic (dev.telnic.org). I'm finding that I have to explicitly name the requested operation and its namespace. Example:
Savon::SOAP.version = 2
client = Savon::Client.new("https://telhosting.opensrs.com/client?wsdl")
client.request.basic_auth("user", "pass")
# Doesn't work
#client.list_domains
# Works
client.list_domains do |soap|
soap.input = "listDomainsRequest"
soap.namespace = "http://xmlns.telnic.org/ws/nsp/client/domain/types-1.0"
end
Running into an error when parsing a WSDL file. Get the following error:
NoMethodError: undefined method `start_with?' for "name":String
from /opt/ruby-enterprise-1.8.6-20090610/lib/ruby/gems/1.8/gems/savon-0.7.3/lib/savon/wsdl_stream.rb:55:in `read_namespaces'
Looking at that line in the source I notice that start_with? is being used on keys when parsing for namespaces. Ruby's API doesn't define a method start_with? for Strings, though RoR does.
Would it be better to do:
@namespaces[key.split(":").last] = value if key =~ /^xmlns:/
instead of:
@namespaces[key.split(":").last] = value if key.start_with? "xmlns:"
Hi,
I'm wrapping a SOAP service and so have to repeat the same
soap block assignments at every SOAP call. Ideally, I'd like to "push" these
assignments up a level.
For example, currently I have something like:
class SomeApi
WSDL = 'https://blah.com?WSDL'
def SomeApi.get_all_freds(param1)
client = Savon::Client.new WSDL
client.get_all_freds do |soap|
soap.namespaces["xmlns:wsdl"] = "urn:http://blah.com/more_blah"
soap.header = { "wsdl:Credentials" => {
"UserName" => :user, "Password" => :pass } }
soap.body = { "wsdl:param" => param1 }
end
end
def SomeApi.get_all_dinos(param2)
client = Savon::Client.new WSDL
client.get_all_dinos do |soap|
soap.namespaces["xmlns:wsdl"] = "urn:http://blah.com/more_blah"
soap.header = { "wsdl:Credentials" => {
"UserName" => :user, "Password" => :pass } }
soap.body = { "wsdl:param" => param2 }
end
end
end
Where I'd like to get to is:
class SomeApi
def SomeApi.get_all_freds(param1)
SomeSoapClient::instance.get_all_freds do |soap|
soap.body = { "wsdl:param" => param1 }
end
end
def SomeApi.get_all_dinos(param2)
SomeSoapClient::instance.get_all_dinos do |soap|
soap.body = { "wsdl:param" => param2 }
end
end
end
with something like:
class SomeSoapClient
private_class_method :new
@@instance = nil
WSDL = 'https://blah.com?WSDL'
def SomeSoapClient.instance
unless @@instance then
@@instance = Savon::Client.new WSDL unless @@instance
@@instance.namespaces["xmlns:wsdl"] = "urn:http://blah.com/more_blah"
@@instance.header = { "wsdl:Credentials" => {
"UserName" => :user, "Password" => :pass } }
end
@@instance
end
end
Any idea how I might get close to this? Or is there a better way? Thanks.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.