1

I'm trying to use built-in XMLRPC in Ruby 1.9. Unfortunately, XMLRPC is not documented on ruby-docs.org, so i have tried to build a test code based on examples found by google:

# Server.rb
require "xmlrpc/server"
server = XMLRPC::Server.new( 1234 )
server.add_handler( "test" ) { |msg| return "responce for #{msg}" }
server.serve()

# Client.rb

require "xmlrpc/client"
server = XMLRPC::Client.new( "localhost", "/", 1234 )
server.call( "test", 42 ) == "responce for 42"

Unfortunately, this is not working on both Windows and OSX. Server.rb fails with cryptic error:

C:/Ruby193/lib/ruby/1.9.1/xmlrpc/client.rb:414:in `call': Uncaught exception unexpected return in method test (XMLRPC::FaultException)
        from client.rb:6:in `<main>'

Maybe anyone knows what is my error?

1
  • If you have ruby19-stdlib.chm under Files/lib/xmlrpc/README.rdoc there is some examples. The urls may not be up to date but the general idea is there. You should share where you got your code from. Commented Mar 28, 2013 at 16:07

4 Answers 4

7

Its another way with block:

#server.rb:
require "xmlrpc/server"
server = XMLRPC::Server.new( 1234 )
server.add_handler('my_test.test') { |msg|"responce for #{msg}" }

#client.rb
require "xmlrpc/client"
client = XMLRPC::Client.new( "localhost", "/", 1234 )
s = client.call('my_test.test','asd')
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks, it was my fault: i forgot the arcane rules that Ruby places on 'return' statement inside block O_O.
3

You got it almost right. Here is a tutorial you can use. Your example needs a little modification, you have to pass an object to add_handler that will be used to serve your RPC calls:

# server.rb
require "xmlrpc/server"

class MyClass
  def dosomething(a)
    "response for #{a}"
  end
end

server = XMLRPC::Server.new( 1234 )
server.add_handler( "test", MyClass.new )
server.serve

# client.rb
require "xmlrpc/client"
server = XMLRPC::Client.new( "localhost", "/", 1234 )
puts server.call( "test.dosomething", 42 ) == "response for 42"

1 Comment

So it's no way to add handler via lock, as written in other tutorials?
2

Please note: the default xmlrpc/client.rb impl. doesn't support client certificates based https connections. If you want it you must either use different lib or patch client.rb with something like:

# HG changeset patch
# User Anonymous Coward <[email protected]>
# Date 1338149770 -10800
# Node ID f0557306c8e4f113507fb3bab8567391949fa302
# Parent  3eae8e8f9e065ff6cdf1c95092ad5cca635c9eac
patch client.rb to support https with client certificate.

diff -r 3eae8e8f9e06 -r f0557306c8e4 client.rb
--- a/client.rb Sun May 27 22:20:18 2012 +0300
+++ b/client.rb Sun May 27 23:16:10 2012 +0300
@@ -292,8 +292,8 @@

     # Constructors -------------------------------------------------------------------

-    def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil, 
-                   user=nil, password=nil, use_ssl=nil, timeout=nil)
+    def initialize(host=nil, path=nil, port=nil, proxy_host=nil, proxy_port=nil,
+        user=nil, password=nil, use_ssl=nil, timeout=nil, cacert=nil, cert=nil, key=nil)

       @http_header_extra = nil
       @http_last_response = nil 
@@ -311,6 +311,10 @@
       if use_ssl
         require "net/https"
         @port = port || 443
+        @cacert = cacert
+        @cert = cert
+        @key = key
+
       else
         @port = port || 80
       end
@@ -325,8 +329,19 @@

       # HTTP object for synchronous calls
       Net::HTTP.version_1_2
-      @http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port) 
-      @http.use_ssl = @use_ssl if @use_ssl
+      @http = Net::HTTP.new(@host, @port, @proxy_host, @proxy_port)
+      if @use_ssl
+        @http.use_ssl = @use_ssl
+        if nil != @cacert
+          @http.ca_file = @cacert
+          @http.verify_mode = OpenSSL::SSL::VERIFY_PEER
+          @http.verify_depth = 5
+        else
+          @http.verify_mode = OpenSSL::SSL::VERIFY_NONE
+        end
+        @http.cert = @cert
+        @http.key = @key
+      end
       @http.read_timeout = @timeout
       @http.open_timeout = @timeout

@@ -366,7 +381,7 @@
       hash.each { |k,v| h[k.to_s.downcase] = v }

       self.new(h['host'], h['path'], h['port'], h['proxy_host'], h['proxy_port'],     h['user'], h['password'],

Comments

1

I think this could help: http://www.ntecs.de/ruby/xmlrpc4r/howto.html

#server.rb
require "xmlrpc/server"
server = XMLRPC::Server.new( 1234 )

class MyHandler
  def test(msg)
        "message #{msg}"
    end
end
server.add_handler(XMLRPC::iPIMethods("my_test"), MyHandler.new)
server.serve

#client.rb
require "xmlrpc/client"
server = XMLRPC::Client.new( "localhost", "/", 1234 )
s = server.call('my_test.test','hello!')

1 Comment

So it's no way to add handler via lock, as written in other tutorials?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.