Tornado Tools

Mongrel2 handler for Tornado

«  adisp   ::   Contents   ::   Caching asynchronous methods  »

Mongrel2 handler for Tornado

A Mongrel2 handler for Tornado based web apps.

Please note that this is considered EXPERIMENTAL! Any feedback is very welcome! Add issues or fork the code at Github!

Usage is quite simple:

from tornadotools.mongrel2.handler import Mongrel2Handler
from zmq.eventloop.ioloop import IOLoop
from zmq.eventloop.ioloop import install as install_ioloop

# install the zmq version of the IOLoop
install_ioloop()

l = IOLoop.instance()

# create the handler with the `tornado.web.Application`
handler = Mongrel2Handler(app, "tcp://127.0.0.1:9999", "tcp://127.0.0.1:9998", io_loop=l)

# start listening for incoming messages from Mongrel2
handler.start()

# enter the ioloop
l.start()

The Mongrel2 configuration could be as simple as this:

test_handler = Handler(
    send_spec = "tcp://127.0.0.1:9999",
    send_ident = "760deb97-b486-4e6a-b801-63fc01e93259",
    recv_spec = "tcp://127.0.0.1:9998",
    recv_ident = ""
)

test = Server(
    uuid = "08eb25ae-50ef-43e2-bb3d-cf70437418fa",
    name = "Test",

    chroot = "./",
    pid_file = "/run/dev.pid",
    access_log = "/logs/dev-access.log",
    error_log = "/logs/dev-error.log",

    default_host = "localhost",
    port = 6767,

    hosts = [
        Host(
            name = "localhost",
            routes={
                "/": test_handler
            }
        )
    ]
)

settings = {
    "upload.temp_store" : "/tmp/mongrel2-uploads/upload.XXXXXX"
}

servers = [test]

When uploading data (files, e.g.), note that in contrast to plain Tornado, the actual file storage is handled by Mongrel2 itself. What you should do in your request handler is something like this:

class Handler(tornado.web.RequestHandler):
    def put(self):
        if self.request.headers.get("x-mongrel2-upload-done", None):
            # file was large, thus handled by mongrel2
            filename = self.request.headers.get("x-mongrel2-upload-done")
            body = open(filename, 'r').read()
        elif len(self.request.files) > 0:
            # Tornado handled the file upload
            pass
        elif len(self.request.body) > 0:
            # small file?!
            pass

To keep Mongrel2 from handling the uploads, you simply have to remove the upload.temp_store setting from the config.

API Documentation

class tornadotools.mongrel2.handler.Mongrel2Handler(request_callback, pull_addr, pub_addr, io_loop=None, zmq_ctx=None, sender_id=None, xheaders=True, no_keep_alive=False)[source]

A Mongrel2 handler class for use with tornado.web.Application.

start()[source]

Start to listen for incoming requests.

class tornadotools.mongrel2.handler.MongrelConnection(m2req, stream, request_callback, no_keep_alive=False, xheaders=False)[source]

Handles the connection to the Mongrel2 server.

We execute the request callback and provide methods for sending data to the server/client and eventually finish the request and HTTP connection.

finish()[source]

Finish this connection.

write(chunk)[source]

Write a chunk of data to the server.

class tornadotools.mongrel2.request.MongrelRequest(sender, conn_id, path, headers, body)[source]

A Mongrel2 request object.

static parse(msg)[source]

Helper method for parsing a Mongrel2 request string and returning a new MongrelRequest instance.

should_close()[source]

Check whether the HTTP connection of this request should be closed after the request is finished.

We check for the Connection HTTP header and for the HTTP Version (only HTTP/1.1 supports keep-alive.

«  adisp   ::   Contents   ::   Caching asynchronous methods  »