1.. _guide.app: 2 3The WSGI application 4==================== 5The WSGI application receives requests and dispatches the appropriate handler, 6returning a response to the client. It stores the URI routes that the app will 7accept, configuration variables and registered objects that can be shared 8between requests. The WSGI app is also responsible for handling uncaught 9exceptions, avoiding that stack traces "leak" to the client when in production. 10Let'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 22Initialization 23-------------- 24The :class:`webapp2.WSGIApplication` class is initialized with three optional 25arguments: 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 31Compared to webapp, only config was added; it is used as a standard way to 32configure extra modules (sessions, internationalization, templates or your 33own app configuration values). 34 35Everything 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 53Router 54------ 55:ref:`guide.routing` is a central piece in webapp2, and its main component is 56the :class:`webapp2.Router` object, available in the application as the 57:attr:`webapp2.WSGIApplication.router` attribute. 58 59The router object is responsible for everything related to mapping URIs to 60handlers. 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 71Using the ``router`` attribute you can, for example, add new routes to the 72application after initialization using the ``add()`` method:: 73 74 import webapp2 75 76 app = webapp2.WSGIApplication() 77 app.router.add((r'/', 'handlers.HelloWorldHandler')) 78 79The router has several methods to override how URIs are matched or built or how 80handlers are adapted or dispatched without even requiring subclassing. For an 81example of extending the default dispatching mechanism, see 82:ref:`Request handlers: returned values <guide.handlers.returned_values>`. 83 84Also check the :class:`Router API documentation <webapp2.Router>` for 85a 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 92Config 93------ 94When instantiating the app, you can pass a configuration dictionary which is 95then accessible through the :attr:`webapp2.WSGIApplication.config` attribute. 96A convention is to define configuration keys for each module, to avoid name 97clashes, but you can define them as you wish, really, unless the module 98requires 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 108Then 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 120Registry 121-------- 122A simple dictionary is available in the application to register instances that 123are shared between requests: it is the :attr:`webapp2.WSGIApplication.registry` 124attribute. It can be used by anything that your app requires and the intention 125is to avoid global variables in modules, so that you can have multiple app 126instances using different configurations: each app has its own extra instances 127for any kind of object that is shared between requests. A simple example that 128registers 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 146The registry can be used to lazily instantiate objects when needed, and keep a 147reference in the application to be reused. 148 149A registry dictionary is also available in the 150:ref:`request object <guide.request.registry>`, to store shared objects 151used during a single request. 152 153 154Error handlers 155-------------- 156As described in :ref:`guide.exceptions`, a dictionary is available in the app 157to register error handlers as the :attr:`webapp2.WSGIApplication.error_handlers` 158attribute. They will be used as a last resource if exceptions are not caught 159by handlers. It is a good idea to set at least error handlers for 404 and 500 160status 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 183Debug flag 184---------- 185A debug flag is passed to the WSGI application on instantiation and is 186available as the :attr:`webapp2.WSGIApplication.debug` attribute. When in 187debug mode, any exception that is now caught is raised and the stack trace is 188displayed to the client, which helps debugging. When not in debug mode, a 189'500 Internal Server Error' is displayed instead. 190 191You can use that flag to set special behaviors for the application during 192development. 193 194For App Engine, it is possible to detect if the code is running using the SDK 195or 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 208Thread-safe application 209----------------------- 210By default, webapp2 is thread-safe when the module 211:class:`webapp2_extras.local` is available. This means that it can be used 212outside of App Engine or in the upcoming App Engine Python 2.7 runtime. 213This also works in non-threaded environments such as App Engine Python 2.5. 214 215See in the :ref:`tutorials.quickstart.nogae` tutorial an explanation on how 216to use webapp2 outside of App Engine. 217 218 219Running the app 220--------------- 221The application is executed in a CGI environment using the method 222:meth:`webapp2.WSGIApplication.run`. When using App Engine, it uses 223the 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 244Unit testing 245------------ 246As described in :ref:`guide.testing`, the application has a convenience method 247to test handlers: :meth:`webapp2.WSGIApplication.get_response`. It 248receives the same parameters as ``Request.blank()`` to build a request and call 249the 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 263Getting the current app 264----------------------- 265The active ``WSGIApplication`` instance can be accessed at any place of your 266app using the function :func:`webapp2.get_app`. This is useful, for example, to 267access 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