Writing Handlers

Creating new handlers is done by implementing a class with a specific signature.

You can inherit from the base class Vaurien provides and just implement the __call__ method:

from vaurien.handlers import BaseHandler

class MySuperHandler(BaseHandler):

    name = 'super'
    options = {}

    def __call__(self, client_sock, backend_sock, to_backend):
        # do something here

Vaurien can use this handler and call it everytime data is being seen on one hand or the other.

Where:

  • name - the name under which your backend is known
  • options - a mapping containing your handler options
  • client_sock - the socket opened with the client
  • backend_sock - the socket opened with the backend server
  • to_backend - a boolean giving the direction of the call. If True it means some data is available in the client socket, that is supposed to go to the backend. If False, it means data is available on the backend socket and should be tramsmitted back to the client.

A handler instance is initialized with two values:

  • settings - the settings loaded for the handler
  • proxy - the proxy instance

For the handler options, each option is defined in the options mapping. The key is the option name and the value is a 3-tuple providing:

  • a description
  • a type
  • a default value

every option is optional and need a default value

Full handler example

Here is how the delay handler is specified:

from vaurien.handlers import BaseHandler

class Delay(BaseHandler):
    """Adds a delay before the backend is called.
    """
    name = 'delay'
    options = {'sleep': ("Delay in seconds", int, 1),
            'before':
                    ("If True adds before the backend is called. Otherwise"
                    " after", bool, True)}

    def __call__(self, client_sock, backend_sock, to_backend):
        before = to_backend and self.options('before')
        after = not to_backend and not self.options('before')

        if before:
            gevent.sleep(self.options('sleep'))

        data = self._get_data(client_sock, backend_sock, to_backend)

        if after:
            gevent.sleep(self.options('sleep'))

        if data:
            dest = to_backend and backend_sock or client_sock
            dest.sendall(data)

Using handlers

Once the handler is ready, you can point it to Vaurien by providing its fully qualified name - e.g. the class name prefixed by the module and package(s) names.

Then you can use it with the –behavior option:

$ vaurien --local localhost:8000 --distant google.com:80 \
    --behavior 20:path.to.the.callable \
    --handlers.delay.sleep 2

Or by using a configuration file:

[vaurien]
behavior = 20:foobar

[handler:foobar]
callable = path.to.the.callable
foo=bar

And calling Vaurien with –config:

$ vaurien --config config.ini

Project Versions

Table Of Contents

Previous topic

Handlers

This Page