# Hooks and Wrappers

TurboGears defines three ways to plug behaviors inside existing applications and plugins: Hooks, Controller Wrappers and Application Wrappers.

Hooks work in an event registration and notification manner, they permit to emit events and notify registered listeners which are able to perform actions depending on the event itself.

Controller Wrappers sits between TurboGears and the controller body code, they permit to extend controllers code much like a decorator, but can be attached to third party controllers or application wide to any controller.

Application Wrappers are much like WSGI middlewares but behave and work in the TurboGears context, so they receive the TurboGears context and Request instead of the WSGI environ and are expected to return a webob.Response object back.

## Hooks

TurboGears allows you to attach callables to a wide set of events. Most of those are available as both controller events and system wide events.

To register a system wide even you can use the `register` method of the `tg.hooks` object. As some hooks require being registered before the application is running, it’s common practice to register them in your `app_cfg.py` file:

    def on_startup():
        print 'hello, startup world'

    def on_shutdown():
        print 'hello, shutdown world'

    def before_render(remainder, params, output):
        print 'system wide before render'

    # ... (base_config init code)
    tg.hooks.register('startup', on_startup)
    tg.hooks.register('shutdown', on_shutdown)
    tg.hooks.register('before_render', before_render)

To register controller based hooks you can use the event decorators:

    from tg.decorators import before_render

    def before_render_cb(remainder, params, output):
        print 'Going to render', output

    class MyController(TGController):
        @expose()
        @before_render(before_render_cb)
        def index(self, *args, **kw):
            return dict(page='index')

Or register them explicitly (useful when registering hooks on third party controllers):

    tg.hooks.register('before_render', before_render_cb, controller=MyController.index)

See `tg.configuration.hooks.HooksNamespace.register()` for more details on registering hooks.

Apart from Hooks TurboGears also provide some Configuration Milestones you might want to have a look at to check whenever it is more proper to register an action for a configuration milestone or for an hook.

### Available Hooks

- `startup()` - application wide only, called when the application starts

- `shutdown()` - application wide only, called when the application exits

- `configure_new_app(app)` - new application got created by the application configurator.

    This is the only call that can guarantee to receive the TGApp instance before any middleware wrapping.

- `before_config(app) -> app` - application wide only, called right after creating application,

    but before setting up most of the options and middleware. Must return the application itself. Can be used to wrap the application into middlewares that have to be executed having the full TG stack available.

- `after_config(app) -> app` - application wide only, called after finishing setting everything up.

    Must return the application iself. Can be used to wrap the application into middleware that have to be executed before the TG ones. Can also be used to modify the Application by mounting additional subcontrollers inside the RootController.

- `before_validate(remainder, params)` - Called before performing validation

- `before_call(remainder, params)` - Called after valdation, before calling the actual controller method

- `before_render(remainder, params, output)` - Called before rendering a controller template, `output` is the controller return value

- `after_render(response)` - Called after finishing rendering a controller template

### Notifying Custom Hooks

Custom hooks can be notified using `tg.hooks.notify`, listeners can register for any hook name, so it as simple as notifying your own hook and documenting them in your library documentation to make possible for other developers to listen for them:

    tg.hooks.notify('custom_global_hook')

See `tg.configuration.hooks.HooksNamespace.notify()` for more details.

## Controller Wrappers

Controller wrappers behave much like decorators, they sit between the controller code and TurboGears. Whenever turbogears has to call that controller it will process all the registered controller wrappers which are able to forward the request to the next in chain or just directly return an alternative value from the controller.

Registering a controller wrapper can be done using `AppConfig.register_controller_wrapper`. It is possible to register a controller wrapper for a specific controller or for the whole application, when registered to the whole application they will be applied to every controller of the application or third party libraries:

    def controller_wrapper(next_caller):
        def call(*args, **kw):
            try:
                print 'Before handler!'
                return next_caller(*args, **kw)
            finally:
                print 'After Handler!'
        return call

    base_config.register_controller_wrapper(controller_wrapper)

Due to the registration performance cost, controller wrappers can only be registered before the application started.

See `AppConfig.register_controller_wrapper()` for more details.

## Application Wrappers

Application wrappers are like WSGI middlewares but are executed in the context of TurboGears and work with abstractions like Request and Respone objects.

Application wrappers are callables built by passing the next handler in chain and the current TurboGears configuration.

They are usually subclasses of `ApplicationWrapper` which provides the expected interface.

Every wrapper, when called, is expected to accept the WSGI environment and a TurboGears context as parameters and are expected to return a `tg.request_local.Response` instance:

    from tg.appwrappers.base import ApplicationWrapper

    class AppWrapper(ApplicationWrapper):
        def __init__(self, handler, config):
            super(AppWrapper, self).__init__(handler, config)

        def __call__(self, controller, environ, context):
            print 'Going to run %s' % context.request.path
            return self.next_handler(controller, environ, context)

Application wrappers can be registered from you application configuration object in `app_cfg.py`:

    base_config.register_wrapper(AppWrapper)

When registering a wrapper, it is also possible to specify after which other wrapper it has to run if available:

    base_config.register_wrapper(AppWrapper, after=OtherWrapper)

Wrappers registered with `after=False` will run before any other available wrapper (in order of registration):

    base_config.register_wrapper(AppWrapper, after=False)

See `AppConfig.register_wrapper()` for more details.