How do I create a Ruby SOAP client without using a WSDL? - ruby

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

Related

Need help handling Timeout::Error in Savon

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

SAVON passing XML as a request to wsdl and getting response as xml

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

how to call method in one application from another application in ruby on rails

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.

Ruby Savon : How to get the request text sent to server?

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

REST Client Example in Ruby

Can anyone explain me with an example, by using REST Client to do GET/POST/PUT operations in a Rest web service?
In POST/PUT, using REST Client, need to pass the whole xml body to do
POST/PUT operations.
For example, Using REST Client
I need to get the content of a service using,
RESTClient.get(url)
POST an xml to an url:
RESTClient.post(url,entirexml)
PUT an xml to an URL:
RESTClient.put(url,entirexml)
DELETE using REST CLIENT.
Can anyone help me with examples for all the REST Client HTTP METHODS with example?
I need to send the whole XML along with namespace to a rest service using PUT/POST operations of REST Client.
If anyone have examples on this, kindly post then please.
require 'rest-client'
RestClient.get 'http://example.com/resource', {:params => {:id => 50, 'foo' => 'bar'}}
RestClient.get 'http://example.com/resource'
xml = '<xml><foo>bar</foo><bar>foo</bar></xml>'
RestClient.post 'http://example.com/resource', xml , {:content_type => :xml}
RestClient.put 'http://example.com/resource', xml , {:content_type => :xml}
RestClient.delete 'http://example.com/resource'
See more examples and documentation at https://github.com/rest-client/rest-client
The Readme file at the git site for the rest-client gem has a whole bunch of examples of how to do requests, include parameters, etc.
I'd start with that.
If there are specific things that are not working, then it generally helps to post the code you've tried that you think SHOULD be working, and then it's usually easier for people to tell where you are going wrong.

Resources