Toto 1.0.10 documentation

Servers, Handlers and Sessions

«  The Toto web server   ::   Contents   ::   Method Decorators  »

Servers, Handlers and Sessions

The Toto server and handler classes are designed to simplify most of the boilerplate that comes with building web services so you can focus on the important parts specific to your application.

Most of the time you’ll only need this script to start your server:

from toto.server import TotoServer

TotoServer('settings.conf').run()

Methods, startup functions and databases can all be configured with the conf file.

Run your startup script with –help to see all available options.

Server

class toto.server.TotoServer(conf_file=None, **kwargs)[source]

Instances can be configured in three ways:

  1. (Most common) Pass the path to a config file as the first parameter to the constructor.
  2. Pass config parameters as command line arguments to the initialization script.
  3. Pass keyword arguments to the constructor.

Precidence is as follows:

Keyword args, config file, command line

The following method will normally be your only interaction with an instance of TotoServer

TotoServer.run()

Start the service. Depending on the initialization options, this may run more than one service process.

Handler

class toto.handler.TotoHandler(application, request, **kwargs)[source]

The handler is responsible for processing all requests to the server. An instance will be initialized for each incoming request and will handle authentication, session management and method delegation for you.

You can set the module to use for method delegation via the method_module parameter. Methods are modules that contain an invoke function:

def invoke(handler, parameters)

The request handler will be passed as the first parameter to the invoke function and provides access to the server’s database connection, the current session and other useful request properties. Request parameters will be passed as the second argument to the invoke function. Any return values from invoke() functions should be JSON serializable.

Toto methods are generally invoked via a POST request to the server with a JSON serialized object as the body. The body should contain two properties:

  1. method - The name of the method to invoke.
  2. parameters - Any parameters to pass to the Toto function.

For example:

{"method": "account.create", "parameters": {"user_id": "test", "password": "testpassword"}}

Will call method_module.account.create.invoke(handler, {‘user_id’: ‘test’, ‘password’: ‘testpassword’})

An invoke() function can be decorated with @tornado.gen.coroutine and be run as a Tornado coroutine.

Alternatively, an invoke(handler, parameters) function may be decorated with @toto.invocation.asynchronous. If a function decorated in this manner does not return a value, the connection well remain open until handler.respond(result, error) is called where error is an Exception or None and result is a normal invoke() return value or None.

There are client libraries for iOS and Javascript that will make using Toto much easier. They are available at https://github.com/JeremyOT/TotoClient-iOS and https://github.com/JeremyOT/TotoClient-JS respectively.

Response paths

TotoHandler.respond(result=None, error=None, batch_results=None, allow_async=True)[source]

Respond to the request with the given result or error object (the batch_results and allow_async parameters are for internal use only and not intended to be supplied manually). Responses will be serialized according to the response_type propery. The default serialization is “application/json”. Other supported protocols are:

  • application/bson - requires pymongo
  • application/msgpack - requires msgpack-python

The response will also contain any available session information.

To help with error handling in asynchronous methods, calling handler.respond(error=<your_error>) with a caught exception will trigger a normal Toto error response, log the error and finish the request. This is the same basic flow that is used internally when exceptions are raised from synchronous method calls.

The “error” property of the response is derived from the error parameter in the following ways:

  1. If error is an instance of TotoException, “error” will be a dictionary with “value” and “code” keys matching those of the TotoException.
  2. In all other cases, error is first converted to a TotoException with code = <ERROR_SERVER> and value = str(error) before following (1.).

To send custom error information, pass an instance of TotoException with value = <some_json_serializable_object>.

TotoHandler.respond_raw(body, content_type, finish=True)[source]

Respond raw is used by respond to send the response to the client. You can pass a string as the body parameter and it will be written directly to the response stream. The response “content-type” header will be set to content_type. Use finish to specify whether or not the response stream should be closed after body is written. Use finish=False to send the response in multiple calls to respond_raw.

TotoHandler.on_connection_close()[source]

You should not call this method directly, but if you implement an on_connection_close() function in a method module (where you defined invoke) it will be called when the connection closes if that method was invoked. E.G.:

def invoke(handler, parameters):
  #main method body

def on_connection_close(handler):
  #clean up
toto.handler.TotoHandler.headers_only

Will be set to True if the handler is expected to send only response headers. By default, this will only be set for “HEAD” requests. When True, respond() and respond_raw() will not write a body. Check this property in method implementations to avoid performing unnecessary work when a body is not required.

Event Framework

TotoHandler.register_event_handler(event_name, handler, run_on_main_loop=True, deregister_on_finish=False)[source]

If using Toto’s event framework, this method makes it easy to register an event callback tied to the current connection and handler. Event handlers registered via this method will not be called once this handler has finished (connection closed). The deregister_on_finish parameter will cause this handler to be explicitly deregisted as part of the handler.on_finish event. Otherwise, event handlers are only cleaned up when the associated event is received.

The return value can be used to manually deregister the event handler at a later point.

TotoHandler.deregister_event_handler(sig)[source]

Pass the value returned from register_event_handler to deregister an active event handler.

Batch Requests

class toto.handler.BatchHandlerProxy(handler, request_key)[source]

A proxy to a handler, this class intercepts calls to handler.respond() in order to match the response to the proper batch request_key. If a method is invoked as part of a batch request, an instance of BatchHandlerProxy will be passed instead of a TotoHandler. Though this replacement should be transparent to the method invocation, you may access the underlying handler with proxy.handler.

BatchHandlerProxy.respond(result=None, error=None, allow_async=True)[source]

Sets the response for the corresponding batch request_key. When all requests have been processed, the combined response will passed to the underlying handler’s respond().

The allow_async parameter is for internal use only and is not intended to be supplied manually.

Instrumentation

classmethod TotoHandler.set_before_handler(handler)[source]

Set the handler that will be called before any method invocation. This is useful for instrumentation. The handler will be called with handler, transaction_id, method, where transaction_id is a UUID and method is the name of the invoked method. For batch requests each invocation will be tracked and logged separately, but there will also be a message logged with name "<batch>" which wraps the entire request. The default handler is a no op.

classmethod TotoHandler.set_after_handler(handler)[source]

Set the handler that will be called after any method invocation. The handler will be called with handler, transaction_id, where transaction_id is the UUID that was passed to the before handler. The default handler is a no op.

Sessions

TotoHandler.create_session(user_id=None, password=None, verify_password=True)[source]

Create a new session for the given user id and password (or an anonymous session if user_id is None). After this method is called, the session will be available via self.session. As with the db_connection.create_session() method, you may pass verify_password=False to create a session without checking the password. This can be used to implement alternative authentication methods like Facebook, Twitter and Google+.

TotoHandler.retrieve_session(session_id=None)[source]

Retrieve the session specified by the request headers (or if enabled, the request cookie) and store it in self.session. Alternatively, pass a session_id to this function to retrieve that session explicitly.

If the hmac_enabled option is set to True, Verify the session against the given request. Expects that the request’s x-toto-hmac header is the sha1 hmac of the request signature signed with the authenticated key.

The signature takes the form: method + uri + body or ''

classmethod TotoHandler.set_hmac_handler(handler)[source]

Set the hmac verification function. It will be called with handler(session, request, headers) and may be used to add additional verification or to modify the signature used for validation, e.g. to confirm request time.

classmethod TotoHandler.set_response_hmac_handler(handler)[source]

Set the hmac generation function for responses. It will be called with handler(session, response_body) and may be used to add to modify the signature used for validation. It must return a string.

The TotoSession class

class toto.session.TotoSession(db, session_data, session_cache=None, key=None)[source]

Instances of TotoSession provide dictionary-like access to current session variables, and the current account (if authenticated).

TotoSession.refresh()[source]

Refresh the current session to the state in the database.

TotoSession.save()[source]

Save the session to the database.

TotoSession.get_account(*args)[source]

Load the account associated with this session (if authenticated). Session properties are serialized to a binary string and stored as the TotoSession.state property, so you don’t need to configure your database to handle them in advance.

classmethod TotoSession.set_serializer(serializer)[source]

Set the module that instances of TotoSession and TotoSessionCache will use to serialize session state. The module must implement loads and dumps and support serialization and deserialization of any data you want to store in the session. By default, cPickle is used.

classmethod TotoSession.loads(data)[source]

A convenience method to call serializer.loads() on the active serializer.

classmethod TotoSession.dumps(data)[source]

A convenience method to call serializer.dumps() on the active serializer.

classmethod TotoSession.generate_id()[source]

Generate a random 22 character url safe session ID string.

The TotoSessionCache class

class toto.session.TotoSessionCache[source]

Instances of TotoSessionCache allow for sessions to be stored separately from the main application database. As sessions must be retrieved for each authenticated request, it can be useful to keep them in a specialized database (redis, memcached) separate from the rest of your data.

Note: cached sessions cannot currently be removed before their expiry.

TotoSessionCache.store_session(session_data)[source]

Store a TotoSession with the given session_data. session_data can be expected to contain, at a minimum, session_id and expires. If an existing session matches the session_id contained in session_data, it should be overwritten. The session is expected to be removed after the time specified by expires. The storage implementation is allowed to change the session’s session_id if needed by returning the new id. Returning any falsey value will not affect the session_id.

TotoSessionCache.load_session(session_id)[source]

Retrieve the session with the given session_id. This method should return the session_data dict that was originally passed to store_session().

class toto.clientsessioncache.ClientCache(cipher, hmac_key)[source]

A TotoSessionCache implementation that stores all session data with the client. Depending on use, the session may be sent as a header or cookie. ClientCache works by storing the encrypted session state in the session ID and decrypting it on each request. When using this method, it is important to keep session state small as it can add significant overhead to each request.

cipher will be used to encrypt and decrypt the session data. It should be identical between all servers in a deployment to allow proper request balancing. cipher is expected to implement encrypt(data) and the reverse decrypt(data) both accepting and returning str objects.

class toto.clientsessioncache.AESCipher(key, iv=None)[source]

A convenient cipher implementation for AES encryption and decryption.

Create a new AESCipher with the given key and iv that wraps Crypto.AES but is reusable and thread safe. For convenience, both the key and iv may be provided as one string, in which case the last AES.block_size (16) bytes will be used for iv.

class toto.redisconnection.RedisSessionCache(db)[source]

A TotoSessionCache implementation that uses Redis for session storage. Useful for improving the speed of authenticated requests while still allowing account data to live in e.g. MySQL.

db must be an instance of redis.StrictRedis initialized to the target database.

The TotoAccount class

class toto.session.TotoAccount(session)[source]

Instances of TotoAccount provide dictionary-like access to user account properties. Unlike sessions, account properties are loaded directly from distinct fields in the database so if you’re not using a schemaless database you’ll need to make sure the fields (columns) exist in advance.

TotoAccount.load_property(*args)[source]

Load the properties passed to args. Properties will be dynamically loaded as they are accessed, but if you know you’ll be referencing multiple properties, it can be faster to load them in bulk by passing all the keys you want to load as arguments to this method first.

TotoAccount.save()[source]

Save any modified keys to the user account stored in the database.

«  The Toto web server   ::   Contents   ::   Method Decorators  »