The router is the message processing component of RapidSMS. It provides the infrastructure to receive incoming and send outgoing messages, and triggers a series of phases through which applications process messages. Each RapidSMS project can use exactly one router, which should be chosen based on the needs of the project.
Application and router behavior in RapidSMS are intertwined. In this section, we focus on the behavior specific to the router, with references to some key areas where this behavior is tied to applications. For more information about processing messages in applications, see the applications documentation.
Each RapidSMS project can use exactly one router, which should be chosen based on the needs of the project. The path to your chosen router must go in the RAPIDSMS_ROUTER setting:
RAPIDSMS_ROUTER = 'path.to.your.RouterClass'
The default router is rapidsms.router.blocking.BlockingRouter.
The choice of router is an important decision that will affect your message processing performance. For example, some routers are easy to set up but will struggle with large message volumes. More complex routers may process messages more efficiently, but require more work to set up.
The router maintains a collection of related applications through which it routes incoming and outgoing messages, as well as a collection of backends through which it can send outgoing messages. Applications and backends can be added manually by the user, or managed by the router implementation. For example, BlockingRouter loads them upon initialization.
BaseRouter.add_app takes one argument that is either an AppBase subclass or the name of a RapidSMS application’s containing Django app. If the argument is the name of a Django app, the method looks in app_name.app for an AppBase subclass to use. The method then instantiates the subclass and adds it to the router’s list of associated applications, apps.
In general, the send and receive methods in the messaging api abstract the logic needed for passing messages to the router. In the incoming and outgoing router methods, messages are passed to the router’s associated applications for processing.
Note
See also the application documentation on incoming message processing.
In BaseRouter.receive_incoming, the incoming message is processed in five phases. Each application provides code for executing the phases. The router method defines hooks which allow an application to filter out a message, skip phases, or stop further processing.
The order in which the router chooses applications to process messages is extremely important, because each application will have the opportunity to block subsequent applications from processing a message. In BaseRouter.receive_incoming, the message is processed by applications in the order they are listed in the apps list property. For BlockingRouter, this means that messages are processed by applications in the order they are listed in INSTALLED_APPS.
Note
See also the application documentation on outgoing message processing.
In BaseRouter.send_outgoing, the outgoing message is processed sequentially by the applications listed in the apps list property. However, the applications are called in reverse order with respect to the order they are called in BaseRouter.receive_incoming, so the first application called to process an incoming message is the last application that is called to process an outgoing message. If any application returns True during the outgoing phase, all further processing of the message will be aborted.
All routers should extend from rapidsms.router.base.BaseRouter. The BaseRouter is a fully-functional router that provides basic implementations of all router methods. Subclasses may override the default methods to enhance convenience or optimize performance.
New in version 0.10.0: Please, see the release notes
RapidSMS provides an easy-to-use default router at rapidsms.router.blocking.BlockingRouter. As its name suggests, BlockingRouter handles messages synchronously, waiting for all application and backend processing to complete before continuing. This is acceptable for many scenarios, but will be less efficient if your project needs to handle many inbound and outbound messages.
BlockingRouter adds apps and backends upon initialization. By default, it searches for relevant classes in the Django apps in INSTALLED_APPS and INSTALLED_BACKENDS. Alternatively, you may provide specific classes or Django apps in which to search in the apps and backends list arguments. To illustrate:
>>> from django.conf import settings
>>> from rapidsms.router.blocking import BlockingRouter
>>> print settings.INSTALLED_APPS
['rapidsms.contrib.handlers', 'rapidsms.contrib.default',
'rapidsms.contrib.locations', 'rapidsms.contrib.messagelog',
... (other Django apps) ...]
>>> print settings.INSTALLED_BACKENDS
{'message_tester': {'ENGINE': 'rapidsms.contrib.httptester.backend'}}
>>> router = BlockingRouter()
>>> router.apps
[<app: handlers>, <app: default>, <app: locations>, <app: messagelog>]
>>> router.backends
{'message_tester': <backend: message_tester>}
BlockingRouter also overrides BaseRouter.receive_incoming to automatically handle (via the outgoing method) responses to the incoming message.
While RapidSMS includes support for a number of routers out-of-the-box, sometimes you might want to use a customized router. To use an external router with RapidSMS, use the Python import path to the router class for the RAPIDSMS_ROUTER setting, like so:
RAPIDSMS_ROUTER = 'path.to.router'
If you’re building your own router, you can use the standard routers as reference implementations.