API Documentation¶
Running your Application¶
This library exposes a utility function named sprockets.http.run()
for running your application. You need to pass in a callable that accepts
keyword parameters destined for tornado.web.Application
and return
the application instance.
-
sprockets.http.
run
(create_application, settings=None, log_config=<object object>)[source]¶ Run a Tornado create_application.
- Parameters
create_application – function to call to create a new application instance
settings (dict|None) – optional configuration dictionary that will be passed through to
create_application
as kwargs.log_config (dict|None) – optional logging configuration dictionary to use. By default, a reasonable logging configuration is generated based on settings. If you need to override the configuration, then use this parameter. It is passed as-is to
logging.config.dictConfig()
.
settings[‘debug’]
If the settings parameter includes a value for the
debug
key, then the application will be run in Tornado debug mode.If the settings parameter does not include a
debug
key, then debug mode will be enabled based on theDEBUG
environment variable.settings[‘port’]
If the settings parameter includes a value for the
port
key, then the application will be configured to listen on the specified port. If this key is not present, then thePORT
environment variable determines which port to bind to. The default port is 8000 if nothing overrides it.settings[‘number_of_procs’]
If the settings parameter includes a value for the
number_of_procs
key, then the application will be configured to run this many processes unless in debug mode. This is passed toHTTPServer.start
.settings[‘xheaders’]
If the settings parameter includes a value for the
xheaders
key, then the application will be configured to use headers, like X-Real-IP, to get the user’s IP address instead of attributing all traffic to the load balancer’s IP address. When running behind a load balancer like nginx, it is recommended to pass xheaders=True. The default value is True if nothing overrides it.
def create_application(**settings):
return web.Application(
[
# add your handlers here
], **settings)
if __name__ == '__main__':
sprockets.http.run(create_application)
Since sprockets.http.run()
accepts any callable, you can pass a
class instance in as well. The sprockets.http.app.Application
is a specialization of tornado.web.Application
that includes
state management callbacks that work together with the run
function
and provide hooks for performing initialization and shutdown tasks.
The following example uses sprockets.http.app.Application
as a
base class to implement asynchronously connecting to a mythical database
when the application starts.
from tornado import locks, web
from sprockets.http import app, run
class Application(app.Application):
def __init__(self, *args, **kwargs):
handlers = [
# insert your handlers here
]
super().__init__(handlers, *args, **kwargs)
self.ready_to_serve = locks.Event()
self.ready_to_serve.clear()
self.on_start_callbacks.append(self._connect_to_database)
def _connect_to_database(self, _self, iol):
def on_connected(future):
if future.exception():
iol.call_later(0.5, self._connect_to_database, _self, iol)
else:
self.ready_to_serve.set()
future = dbconnector.connect()
iol.add_future(future, on_connected)
if __name__ == '__main__':
run(Application)
Implementing a ready_to_serve
event is a useful paradigm for applications
that need to asynchronously initialize before they can service requests. We
can continue the example and add a /status
endpoint that makes use of
the event:
class StatusHandler(web.RequestHandler):
@gen.coroutine
def prepare(self):
maybe_future = super().prepare()
if concurrent.is_future(maybe_future):
yield maybe_future
if not self._finished and not self.application.ready_to_serve.is_set():
self.set_header('Retry-After', '5')
self.set_status(503, 'Not Ready')
self.finish()
def get(self):
self.set_status(200)
self.write(json.dumps({'status': 'ok'})
Before Run Callbacks¶
This set of callbacks is invoked after Tornado forks sub-processes
(based on the number_of_procs
setting) and before
start()
is called. Callbacks can
safely access the IOLoop
without causing
the start()
method to explode.
If any callback raises an exception, then the application is terminated before the IOLoop is started.
See also
On Start Callbacks¶
This set of callbacks is invoked after Tornado forks sub-processes
(using tornado.ioloop.IOLoop.spawn_callback()
) and after
start()
is called.
See also
Shutdown Callbacks¶
When the application receives a stop signal, it will run each of the callbacks before terminating the application instance. Exceptions raised by the callbacks are simply logged.
See also
Testing your Application¶
The SprocketsHttpTestCase
class makes
it simple to test sprockets.http based applications. It knows how to
call the appropriate callbacks at the appropriate time. Use this as a
base class in place of AsyncHTTPTestCase
and
modify your get_app
method to set self.app
.
-
class
sprockets.http.testing.
SprocketsHttpTestCase
(methodName: str = 'runTest')[source]¶ Test case that correctly runs a sprockets.http.app.Application.
This test case correctly starts and stops a sprockets.http Application by calling the
start()
andstop()
methods duringsetUp
andtearDown
.-
get_app
()[source]¶ Override this method to create your application.
Make sure to set
self.app
before returning.
-
setUp
()[source]¶ Hook method for setting up the test fixture before exercising it.
The sprockets.http application is started by calling the
start()
method after the application is created.
-
shutdown_limit
= 0.25¶ Maximum number of seconds to wait for the application to shut down.
-
tearDown
()[source]¶ Hook method for deconstructing the test fixture after exercising it.
The sprockets.http application is fully stopped by calling the
stop()
and running the ioloop before stopping the ioloop. The shutdown timing is configured using theshutdown_limit
andwait_timeout
variables.
-
wait_timeout
= 0.05¶ Number of seconds to wait between checking for pending callbacks.
-
Response Logging¶
Version 0.5.0 introduced the sprockets.http.mixins
module with
two simple classes - LoggingHandler
and ErrorLogger
. Together they ensure
that errors emitted from your handlers will be logged in a consistent
manner. All too often request handlers simply call write_error
to report a failure to the caller with code that looks something like:
class MyHandler(web.RequestHandler):
def get(self):
try:
do_something()
except Failure:
self.send_error(500, reason='Uh oh')
return
This makes debugging an application fun since your caller generally has more information about the failure than you do :/
By adding ErrorLogger
into the inheritance
chain, your error will be emitted to the application log as if you had
written the following instead:
class MyHandler(web.RequestHandler):
def initialize(self):
super().initialize()
self.logger = logging.getLogger('MyHandler')
def get(self):
try:
do_something()
except Failure:
self.logger.error('%s %s failed with %d: %s',
self.request.method, self.request.uri,
500, 'Uh oh')
self.send_error(500, reason='Uh oh')
return
It doesn’t look like much, but the error reporting is a little more interesting than that – 4XX errors are reported as a warning, exceptions will include the stack traces, etc.
-
class
sprockets.http.mixins.
LoggingHandler
[source]¶ Add
self.logger
.Mix this into your inheritance chain to add a
logger
attribute unless one already exists.-
logger
¶ Instance of
logging.Logger
with the same name as the class.
-
-
class
sprockets.http.mixins.
ErrorLogger
[source]¶ Log a message in
send_error
.Mix this class into your inheritance chain to ensure that errors sent via
tornado.web.RequestHandler.send_error()
andtornado.web.RequestHandler.write_error()
are written to the log.
Standardized Error Response Documents¶
Version 0.5.0 also introduced the ErrorWriter
class which implements write_error
to provide a standard machine-readable
document response instead of the default HTML response that Tornado implements.
If ContentMixin
is being used as well,
write_error
will use
send_response()
to send the
document, otherwise it is sent as JSON.
-
class
sprockets.http.mixins.
ErrorWriter
[source]¶ Write error bodies out consistently.
Mix this class in to your inheritance chain to include error bodies in a machine-readable document format.
If
ContentMixin
is also in use, it will send the error response with it, otherwise the response is sent as a JSON document.The error document has three simple properties:
- type
This is the type of exception that occurred or
null
. It is only set whenwrite_error()
is invoked with a non-emptyexc_info
parameter. In that case, it is set to the name of the first value in thetuple
; IOW,exc_type.__name__
.- message
This is a description of the error. If exception info is present, then the stringified exception value is used as the message (e.g.,
str(exc_value)
); otherwise, the HTTPreason
will be used. If a customreason
is not present, then the standard HTTP reason phrase is used. In the final case of a non-standard HTTP status code with neither an exception nor a custom reason, the stringUnknown
will be used.- traceback
If the application is configured to serve tracebacks and the error was caused by an exception (based on
exc_info
kwarg), then this is the formatted traceback as an array of strings returned fromtraceback.format_exception()
. Otherwise, this property is set tonull
.
Internal Interfaces¶
Run a Tornado HTTP service.
Runner
: encapsulates the running of the applicationRunCommand
: distutils command to runs an application
-
class
sprockets.http.runner.
RunCommand
(dist)[source]¶ Simple distutils.Command that calls
sprockets.http.run()
This is installed as the httprun distutils command when you install the
sprockets.http
module.-
finalize_options
()[source]¶ Set final values for all the options that this command supports. This is always called as late as possible, ie. after any option assignments from the command-line or from other commands have been done. Thus, this is the place to code option dependencies: if ‘foo’ depends on ‘bar’, then it is safe to set ‘foo’ from ‘bar’ as long as ‘foo’ still has the same value it was assigned in ‘initialize_options()’.
This method must be implemented by all command classes.
-
initialize_options
()[source]¶ Set default values for all the options that this command supports. Note that these defaults may be overridden by other commands, by the setup script, by config files, or by the command-line. Thus, this is not the place to code dependencies between options; generally, ‘initialize_options()’ implementations are just a bunch of “self.foo = None” assignments.
This method must be implemented by all command classes.
-
run
()[source]¶ A command’s raison d’etre: carry out the action it exists to perform, controlled by the options initialized in ‘initialize_options()’, customized by other commands, the setup script, the command-line, and config files, and finalized in ‘finalize_options()’. All terminal output and filesystem interaction should be done by ‘run()’.
This method must be implemented by all command classes.
-
-
class
sprockets.http.runner.
Runner
(app, before_run=None, on_start=None, shutdown=None)[source]¶ HTTP service runner.
- Parameters
app (tornado.web.Application) – the application to serve
This class implements the logic necessary to safely run a Tornado HTTP service inside of a docker container.
Usage Example
def make_app(): return web.Application(...) def run(): server = runner.Runner(make_app()) server.start_server() ioloop.IOLoop.instance().start()
The
start_server()
method sets up the necessary signal handling to ensure that we have a clean shutdown in the face of signals.-
run
(port_number, number_of_procs=0)[source]¶ Create the server and run the IOLoop.
- Parameters
If the application’s
debug
setting isTrue
, then we are going to run in a single-process mode; otherwise, we’ll let tornado decide how many sub-processes based on the value of thenumber_of_procs
argument. In any case, the application’s before_run callbacks are invoked. If a callback raises an exception, then the application is terminated by callingsys.exit()
.If any
on_start
callbacks are registered, they will be added to the Tornado IOLoop for execution after the IOLoop is started.The following additional configuration parameters can be set on the
httpserver.HTTPServer
instance by setting them in the application settings:xheaders
,max_body_size
,max_buffer_size
.
-
start_server
(port_number, number_of_procs=0)[source]¶ Create a HTTP server and start it.
- Parameters
If the application’s
debug
setting isTrue
, then we are going to run in a single-process mode; otherwise, we’ll let tornado decide how many sub-processes to spawn.The following additional configuration parameters can be set on the
httpserver.HTTPServer
instance by setting them in the application settings:xheaders
,max_body_size
,max_buffer_size
.
-
class
sprockets.http.app.
Application
(*args, **kwargs)[source]¶ Callback-aware version of
tornado.web.Application
.Using this class instead of the vanilla Tornado
Application
class provides a clean way to customize application-level constructs such as connection pools.Note that much of the functionality is implemented in
CallbackManager
.-
log_request
(handler)[source]¶ Customized access log function.
- Parameters
handler (tornado.web.RequestHandler) –
-
-
class
sprockets.http.app.
CallbackManager
(tornado_application, *args, **kwargs)[source]¶ Application state management.
This is where the core of the application wrapper actually lives. It is responsible for managing and calling the various application callbacks. Sub-classes are responsible for gluing in the actual
tornado.web.Application
object and thesprockets.http.runner
module is responsible for starting up the HTTP stack and calling thestart()
andstop()
methods.-
runner_callbacks
¶ dict
of lists of callback functions to call at certain points in the application lifecycle. Seebefore_run_callbacks
,on_start_callbacks
, andon_shutdown_callbacks
.Deprecated since version 1.4: Use the property callbacks instead of this dictionary. It will be going away in a future release.
-
property
before_run_callbacks
¶ List of synchronous functions called before the IOLoop is started.
The before_run callbacks are called after the IOLoop is created and before it is started. The callbacks are run synchronously and the application will exit if a callback raises an exception.
Signature: callback(application, io_loop)
-
property
on_shutdown_callbacks
¶ List of functions when the application is shutting down.
The on_shutdown callbacks are called after the HTTP server has been stopped. If a callback returns a
tornado.concurrent.Future
instance, then the future is added to the IOLoop.Signature: callback(application)
-
property
on_start_callbacks
¶ List of asynchronous functions spawned before the IOLoop is started.
The on_start callbacks are spawned after the IOLoop is created and before it is started. The callbacks are run asynchronously via
tornado.ioloop.IOLoop.spawn_callback()
as soon as the IOLoop is started.Signature: callback(application, io_loop)
-
start
(io_loop)[source]¶ Run the
before_run
callbacks and queue toon_start
callbacks.- Parameters
io_loop (tornado.ioloop.IOLoop) – loop to start the app on.
-
stop
(io_loop, shutdown_limit=5.0, wait_timeout=1.0)[source]¶ Asynchronously stop the application.
- Parameters
io_loop (tornado.ioloop.IOLoop) – loop to run until all callbacks, timeouts, and queued calls are complete
shutdown_limit (float) – maximum number of seconds to wait before terminating
wait_timeout (float) – number of seconds to wait between checks for pending callbacks & timers
Call this method to start the application shutdown process. The IOLoop will be stopped once the application is completely shut down or after shutdown_limit seconds.
-
property
tornado_application
¶ The underlying
tornado.web.Application
instance.
-
-
sprockets.http.app.
wrap_application
(application, before_run, on_start, shutdown)[source]¶ Wrap a tornado application in a callback-aware wrapper.
- Parameters
application (tornado.web.Application) – application to wrap.
before_run (list|NoneType) – optional list of callbacks to invoke before the IOLoop is started.
on_start (list|NoneType) – optional list of callbacks to register with
spawn_callback()
.shutdown (list|NoneType) – optional list of callbacks to invoke before stopping the IOLoop
- Returns
a wrapped application object
- Return type