Hi I'm using Savon to access some web services.
I'm using this code:
client=Savon.client(
wsdl: "WebService.wsdl",
env_namespace: "S",
convert_request_keys_to: :camelcase
)
response=client.call(:send_doc) do
message(
Attr1: "123",
Attr2: "ABC")
)
How do I get the request text sent to server?
Regards
Fak
Savon 2 provides an Observer interface. You can register an Observer which is notified before the request is send. The interface contains a Builder object where you find the XML content of the request. Builder#pretty() formats the XML content.
class Observer
def notify(_, builder, _, _)
puts builder.pretty
nil
end
end
Savon.observers << Observer.new
Alternativly you can add log: true to your client configuration. It enables the logging of the requests.
client = Savon.client(log: true, ...)
This isn't possible with stable versions of Savon. However, you can get the request using version 3 of Savon (see the Savon website for installation instructions and more detail). Example from the site:
client = Savon.new('http://example.com?wsdl')
operation = client.operation(service_name, port_name, operation_name)
operation.build # returns SOAP request
You could also monkeypatch Savon methods or set up a custom debugger to get this information with your current Savon version. See these StackOverflow answers for more information:
Accessing the request body of a SOAP request with Savon (Ruby on Rails)
View Savon Request XML without Sending to Server
Related
I'm building a connection between REST-API and SOAP API in Ruby (without Rails).
For SOAP calls I use Savon gem, which is great.
However, I cannot figure out from the docs, how does Savon handle Timeout::Error?
Does it raise Savon::HTTPError or Savon::SOAPFault?
Please advise.
I was curious myself. After a bit of experimentation and skimming through Savon sources it seems that transport-level errors aren't handled and translated to Savon's own exception types, but thrown "as is", so if you need to handle them, you have to handle exceptions thrown by the underlying HTTP client library.
It's important to note that Savon supports multiple HTTP clients through the httpi abstraction layer. By default it just chooses one from those being available, but if you need to handle it's exceptions, you shouldn't rely on the automatic selection, but explicitly configure which HTTPI adapter should be used (e.g. HTTPI.adapter = :net_http).
The code below can be used to test the timeout scenario with HTTPI adapter of your choice.
Code for experimentation
Server (written in PHP, because there are no up-to-date working solutions for writing a dead-simple SOAP server like this, without a ton of boilerplate code, in Ruby):
<?php
// simple SOAP server - run with 'php -S localhost:12312 name_of_this_file.php'
class SleepySoapServer
{
public function hello()
{
sleep(3600); // take an hour's nap before responding
return 'Hello, world!';
}
}
$options = array('uri' => 'http://localhost:12312/');
$server = new SoapServer(null, $options);
$server->setClass(SleepySoapServer::class);
$server->handle();
Client (using Savon 2):
require 'savon'
HTTPI.adapter = :net_http # request Net::HTTP client from the standard library
uri = 'http://localhost:12312'
client = Savon.client do
endpoint uri
namespace uri
end
response = client.call :Hello
p response.body
If you don’t like to rescue errors, here’s how you can tell Savon not to raise them
Savon.configure do |config|
config.raise_errors = false
end
I have a third party application and output of this application is an request xml which needs to be passed in to webservice (WSDL)
I need to do integration testing where i will be getting this request xml.
how can i pass this request xml using savon in Ruby ?
is there anyother way where we can pass request xml and get the output in response xml
i tried using soapui and it works but i am looking for native ruby solution
Hello I found the answer and below is the code
Then (/^I test wsdl$/) do
require 'savon'
require 'nokogiri'
xml_file = File.read("/test.xml")
client = Savon.client(wsdl: '/globalweather.wsdl', ssl_verify_mode: :none, ssl_version: :TLSv1)
response = client.call(:get_cities_by_country, xml: xml_file)
puts response.to_xml
print response.to_xml
end
I want to call the method and get the response in my application from another application in Ruby on Rails technology, but here cross site scripting problem is there. so, i can i resolve this issue please help me it would be great.
http://video_tok.com/courses/get_course
def get_course
#course = Course.find(params[:id])
end
now i want to call this above method from this application which is running in edupdu.com domain
http://edupdu.com/call_course_method
def call_course_method
#course = redirect_to "http://video_tak.com/courses/get_course/1"
end
but it would be redirect into video_tak.com application.
i want to call get_course method and get #course object internally without redirect to another site.
Thanks in advance.
Cross-domain AJAX is indeed a problem, but none that could not be solved. In your get_course method you could return the course objects as a JSON response like so:
render json: #course
From there on you could either retrieve the course through JavaScript (AJAX), here you should use JSONP or inside Rails by issuing a HTTP GET request.
AJAX with JSONP
There is JSONP (JSON with padding), which is a communication technique for JavaScript programs to provide a method to request data from a server in a different domain. Look at
the documentation of jQuery.getJSON() and scroll down to the JSONP section.
If the URL includes the string "callback=?" (or similar, as defined by
the server-side API), the request is treated as JSONP instead. See the
discussion of the jsonp data type in $.ajax() for more details.
HTTP GET request
Simply use the Net::HTTP class:
require 'net/http'
require 'json'
url = URI.parse('http://video_tak.com/courses/get_course/1')
req = Net::HTTP::Get.new(url.to_s)
res = Net::HTTP.start(url.host, url.port) do |http|
http.request(req)
end
course_json = JSON.parse(res.body)
If you provide methods for your model to convert JSON into a domain object of yours, you can take it from there.
RPC
You can also use RPC to invoke methods between different Ruby processes, although I recommend this the least I do not want to omit it. There are several remote procedure call (RPC) libraries. The Ruby standard library provides DRb, but there are also implementations based on Ruby on Rails, for instance the rails-xmlrpc gem which allows you to implement RPC based on the XML-RPC protocol or the alternative protocol using JSON with json-rpcj
You will probably find even more libraries when searching for Rails RPC. From whatever library you pick, the concrete solution will differ.
I need to write a soap client that is capable of sending and receiving soap messages.
This soap service does not have an associated WSDL file and soap4r and savon both seem to require one.
I have an example of what I need to do in Java, see the link below.
http://community.cecid.hku.hk/index.php/product/article/writing_hermes_2_ws_client_under_java/#ebms-2_0-sender-ws
I could use java for this, at this point it seems like it would be easier. However I personally prefer coding in ruby and our company has more ruby resources than java.
Can anyone confirm thats its possible to do something similar to java example in ruby without writing my own specialised soap library?. I need to be able to send a payload, which I believe is usually in the form of a soap attachment.
I am particularly interested in seeing soap4r examples that don't use a WSDL as I have had trouble finding any with google.
Any help much appreciated.
as of Savon v2, the syntax is slightly different
client = Savon.client do
endpoint "http://example.com"
namespace "http://v1.example.com"
end
http://savonrb.com/version2/client.html
Savon does not require a WSDL document. Please take a look at the new documentation. If you know the SOAP endpoint and target namespace, you can execute a SOAP request like this:
client = Savon::Client.new
wsdl.endpoint = "http://example.com"
wsdl.namespace = "http://soap.example.com"
end
client.request :any_soap_action do
soap.body = { :do => "something" }
end
client = Savon::Client.new
wsdl.endpoint = "http://example.com"
wsdl.namspace = "http://soap.example.com"
end
This does not work, it misses a the block name and the "e" in namespace:
client = Savon::Client.new do | wsdl |
wsdl.endpoint = "http://example.com"
wsdl.namespace = "http://soap.example.com"
end
how can I capture response from twitter.com? To make sure that everything went ok?
I am using ruby and ruby twitter gem and the my code is basically like that
oauth = Twitter::OAuth.new('consumer token', 'consumer secret')
oauth.authorize_from_access('access token', 'access secret')
client = Twitter::Base.new(oauth)
client.update('Heeeyyyyoooo from Twitter Gem!')
The update twitter api method will send back a response that will let you know if everything went okay. It can respond in either json or xml, I'm sure the twitter gem is using one or the other as a default. You need to save the return value to a variable and parse it, if you have a status id in there then it worked. Try using a token or secret to check what happens when it errors. I would suggest changing your last line to this
ret = client.update('Heeeyyyyoooo from Twitter Gem!')
and then add this line below that to check out what you got back
puts ret.inspect
or
logger.info ret.inspect
or your choice of logging method
[Edit]
It looked like the twitter gem hides the twitter api's actual response from you, parses it for you and just returns you the relevant bits. in the case of the update method it just returns you the id of your new tweet. you can view the id like this
puts ret.id
If you use another library to connect to the twitter api and need to parse xml or json responses then then the rest of this answer may be what you are looking for.
[/Edit]
If you are not using a gem that parses twitter api responses for you then you will need to use something to parse the twitter api's responses into data that you can do something with. There are tons of ways to do this depending on what format you want to parse (json or xml)
My preferences:
XML : Hpricot : gem install hpricot : http://github.com/hpricot/hpricot
json : json : gem install json : http://github.com/flori/json
Here is more information on what the twitter api update method returns: http://apiwiki.twitter.com/Twitter-REST-API-Method:-statuses%C2%A0update
This worked for me...
begin
resp = Twitter.update(params[:message])
rescue Exception => e
# e.message contains the twitter response
end