Home | History | Annotate | Download | only in guide
      1 .. _guide.app:
      2 
      3 The WSGI application
      4 ====================
      5 The WSGI application receives requests and dispatches the appropriate handler,
      6 returning a response to the client. It stores the URI routes that the app will
      7 accept, configuration variables and registered objects that can be shared
      8 between requests. The WSGI app is also responsible for handling uncaught
      9 exceptions, avoiding that stack traces "leak" to the client when in production.
     10 Let's take an in depth look at it now.
     11 
     12 .. note::
     13    If the WSGI word looks totally unfamiliar to you, read the
     14    `Another Do-It-Yourself Framework`_ tutorial by Ian Bicking. It is a very
     15    recommended introduction to WSGI and you should at least take a quick look
     16    at the concepts, but following the whole tutorial is really worth.
     17 
     18    A more advanced reading is the WSGI specification described in the
     19    `PEP 333 <http://www.python.org/dev/peps/pep-0333/>`_.
     20 
     21 
     22 Initialization
     23 --------------
     24 The :class:`webapp2.WSGIApplication` class is initialized with three optional
     25 arguments:
     26 
     27 - ``routes``: a list of route definitions as described in :ref:`guide.routing`.
     28 - ``debug``: a boolean flag that enables debug mode.
     29 - ``config``: a dictionary of configuration values for the application.
     30 
     31 Compared to webapp, only config was added; it is used as a standard way to
     32 configure extra modules (sessions, internationalization, templates or your
     33 own app configuration values).
     34 
     35 Everything is pretty straighforward::
     36 
     37     import webapp2
     38 
     39     routes = [
     40         (r'/', 'handlers.HelloWorldHandler'),
     41     ]
     42 
     43     config = {}
     44     config['webapp2_extras.sessions'] = {
     45         'secret_key': 'something-very-very-secret',
     46     }
     47 
     48     app = webapp2.WSGIApplication(routes=routes, debug=True, config=config)
     49 
     50 
     51 .. _guide.app.router:
     52 
     53 Router
     54 ------
     55 :ref:`guide.routing` is a central piece in webapp2, and its main component is
     56 the :class:`webapp2.Router` object, available in the application as the
     57 :attr:`webapp2.WSGIApplication.router` attribute.
     58 
     59 The router object is responsible for everything related to mapping URIs to
     60 handlers. The router:
     61 
     62 - Stores registered "routes", which map URIs to the application handlers
     63   that will handle those requests.
     64 - Matches the current request against the registered routes and returns the
     65   handler to be used for that request (or raises a ``HTTPNotFound`` exception
     66   if no handler was found).
     67 - Dispatches the matched handler, i.e., calling it and returning a response
     68   to the ``WSGIApplication``.
     69 - Builds URIs for the registered routes.
     70 
     71 Using the ``router`` attribute you can, for example, add new routes to the
     72 application after initialization using the ``add()`` method::
     73 
     74     import webapp2
     75 
     76     app = webapp2.WSGIApplication()
     77     app.router.add((r'/', 'handlers.HelloWorldHandler'))
     78 
     79 The router has several methods to override how URIs are matched or built or how
     80 handlers are adapted or dispatched without even requiring subclassing. For an
     81 example of extending the default dispatching mechanism, see
     82 :ref:`Request handlers: returned values <guide.handlers.returned_values>`.
     83 
     84 Also check the :class:`Router API documentation <webapp2.Router>` for
     85 a description of the methods :meth:`webapp2.Router.set_matcher`,
     86 :meth:`webapp2.Router.set_dispatcher`, :meth:`webapp2.Router.set_adapter` and
     87 :meth:`webapp2.Router.set_builder`.
     88 
     89 
     90 .. _guide.app.config:
     91 
     92 Config
     93 ------
     94 When instantiating the app, you can pass a configuration dictionary which is
     95 then accessible through the :attr:`webapp2.WSGIApplication.config` attribute.
     96 A convention is to define configuration keys for each module, to avoid name
     97 clashes, but you can define them as you wish, really, unless the module
     98 requires a specific setup. First you define a configuration::
     99 
    100     import webapp2
    101 
    102     config = {'foo': 'bar'}
    103 
    104     app = webapp2.WSGIApplication(routes=[
    105         (r'/', 'handlers.MyHandler'),
    106     ], config=config)
    107 
    108 Then access it as you need. Inside a ``RequestHandler``, for example::
    109 
    110     import webapp2
    111 
    112     class MyHandler(webapp2.RequestHandler):
    113         def get(self):
    114             foo = self.app.config.get('foo')
    115             self.response.write('foo value is %s' % foo)
    116 
    117 
    118 .. _guide.app.registry:
    119 
    120 Registry
    121 --------
    122 A simple dictionary is available in the application to register instances that
    123 are shared between requests: it is the :attr:`webapp2.WSGIApplication.registry`
    124 attribute. It can be used by anything that your app requires and the intention
    125 is to avoid global variables in modules, so that you can have multiple app
    126 instances using different configurations: each app has its own extra instances
    127 for any kind of object that is shared between requests. A simple example that
    128 registers a fictitious ``MyParser`` instance if it is not yet registered::
    129 
    130     import webapp2
    131 
    132     def get_parser():
    133         app = webapp2.get_app()
    134         # Check if the instance is already registered.
    135         my_parser = app.registry.get('my_parser')
    136         if not my_parser:
    137             # Import the class lazily.
    138             cls = webapp2.import_string('my.module.MyParser')
    139             # Instantiate the imported class.
    140             my_parser = cls()
    141             # Register the instance in the registry.
    142             app.registry['my_parser'] = my_parser
    143 
    144         return my_parser
    145 
    146 The registry can be used to lazily instantiate objects when needed, and keep a
    147 reference in the application to be reused.
    148 
    149 A registry dictionary is also available in the
    150 :ref:`request object <guide.request.registry>`, to store shared objects
    151 used during a single request.
    152 
    153 
    154 Error handlers
    155 --------------
    156 As described in :ref:`guide.exceptions`, a dictionary is available in the app
    157 to register error handlers as the :attr:`webapp2.WSGIApplication.error_handlers`
    158 attribute. They will be used as a last resource if exceptions are not caught
    159 by handlers. It is a good idea to set at least error handlers for 404 and 500
    160 status codes::
    161 
    162     import logging
    163 
    164     import webapp2
    165 
    166     def handle_404(request, response, exception):
    167         logging.exception(exception)
    168         response.write('Oops! I could swear this page was here!')
    169         response.set_status(404)
    170 
    171     def handle_500(request, response, exception):
    172         logging.exception(exception)
    173         response.write('A server error occurred!')
    174         response.set_status(500)
    175 
    176     app = webapp2.WSGIApplication([
    177         webapp2.Route(r'/', handler='handlers.HomeHandler', name='home')
    178     ])
    179     app.error_handlers[404] = handle_404
    180     app.error_handlers[500] = handle_500
    181 
    182 
    183 Debug flag
    184 ----------
    185 A debug flag is passed to the WSGI application on instantiation and is
    186 available as the :attr:`webapp2.WSGIApplication.debug` attribute. When in
    187 debug mode, any exception that is now caught is raised and the stack trace is
    188 displayed to the client, which helps debugging. When not in debug mode, a
    189 '500 Internal Server Error' is displayed instead.
    190 
    191 You can use that flag to set special behaviors for the application during
    192 development.
    193 
    194 For App Engine, it is possible to detect if the code is running using the SDK
    195 or in production checking the 'SERVER_SOFTWARE' environ variable::
    196 
    197     import os
    198 
    199     import webapp2
    200 
    201     debug = os.environ.get('SERVER_SOFTWARE', '').startswith('Dev')
    202 
    203     app = webapp2.WSGIApplication(routes=[
    204         (r'/', 'handlers.HelloWorldHandler'),
    205     ], debug=debug)
    206 
    207 
    208 Thread-safe application
    209 -----------------------
    210 By default, webapp2 is thread-safe when the module
    211 :class:`webapp2_extras.local` is available. This means that it can be used
    212 outside of App Engine or in the upcoming App Engine Python 2.7 runtime.
    213 This also works in non-threaded environments such as App Engine Python 2.5.
    214 
    215 See in the :ref:`tutorials.quickstart.nogae` tutorial an explanation on how
    216 to use webapp2 outside of App Engine.
    217 
    218 
    219 Running the app
    220 ---------------
    221 The application is executed in a CGI environment using the method
    222 :meth:`webapp2.WSGIApplication.run`. When using App Engine, it uses
    223 the functions ``run_bare_wsgi_app`` or ``run_wsgi_app`` from
    224 ``google.appengine.ext.webapp.util``. Outside of App Engine, it uses the
    225 :py:mod:`wsgiref.handlers` module. Here's the simplest example::
    226 
    227     import webapp2
    228 
    229     class HelloWebapp2(webapp2.RequestHandler):
    230         def get(self):
    231             self.response.write('Hello, webapp2!')
    232 
    233     app = webapp2.WSGIApplication([
    234         ('/', HelloWebapp2),
    235     ], debug=True)
    236 
    237     def main():
    238         app.run()
    239 
    240     if __name__ == '__main__':
    241         main()
    242 
    243 
    244 Unit testing
    245 ------------
    246 As described in :ref:`guide.testing`, the application has a convenience method
    247 to test handlers: :meth:`webapp2.WSGIApplication.get_response`. It
    248 receives the same parameters as ``Request.blank()`` to build a request and call
    249 the application, returning the resulting response from a handler::
    250 
    251     class HelloHandler(webapp2.RequestHandler):
    252         def get(self):
    253             self.response.write('Hello, world!')
    254 
    255     app = webapp2.WSGIapplication([('/', HelloHandler)])
    256 
    257     # Test the app, passing parameters to build a request.
    258     response = app.get_response('/')
    259     assert response.status_int == 200
    260     assert response.body == 'Hello, world!'
    261 
    262 
    263 Getting the current app
    264 -----------------------
    265 The active ``WSGIApplication`` instance can be accessed at any place of your
    266 app using the function :func:`webapp2.get_app`. This is useful, for example, to
    267 access the app registry or configuration values::
    268 
    269     import webapp2
    270 
    271     app = webapp2.get_app()
    272     config_value = app.config.get('my-config-key')
    273 
    274 
    275 .. _Another Do-It-Yourself Framework: http://docs.webob.org/en/latest/do-it-yourself.html
    276