The Request Context

The request context keeps track of the request-level data during arequest. Rather than passing the request object to each function thatruns during a request, therequest andsession proxiesare accessed instead.

This is similar toThe Application Context, which keeps track of theapplication-level data independent of a request. A correspondingapplication context is pushed when a request context is pushed.

Purpose of the Context

When theFlask application handles a request, it creates aRequest object based on the environment it received from theWSGI server. Because aworker (thread, process, or coroutine dependingon the server) handles only one request at a time, the request data canbe considered global to that worker during that request. Flask uses thetermcontext local for this.

Flask automaticallypushes a request context when handling a request.View functions, error handlers, and other functions that run during arequest will have access to therequest proxy, which points tothe request object for the current request.

Lifetime of the Context

When a Flask application begins handling a request, it pushes a requestcontext, which also pushes anapp context. When therequest ends it pops the request context then the application context.

The context is unique to each thread (or other worker type).request cannot be passed to another thread, the other thread hasa different context space and will not know about the request the parentthread was pointing to.

Context locals are implemented using Python’scontextvars andWerkzeug’sLocalProxy. Python manages thelifetime of context vars automatically, and local proxy wraps thatlow-level interface to make the data easier to work with.

Manually Push a Context

If you try to accessrequest, or anything that uses it, outsidea request context, you’ll get this error message:

RuntimeError: Working outside of request context.This typically means that you attempted to use functionality thatneeded an active HTTP request. Consult the documentation on testingfor information about how to avoid this problem.

This should typically only happen when testing code that expects anactive request. One option is to use thetestclient to simulate a full request. Oryou can usetest_request_context() in awith block, andeverything that runs in the block will have access torequest,populated with your test data.

defgenerate_report(year):format=request.args.get("format")...withapp.test_request_context("/make_report/2017",query_string={"format":"short"}):generate_report()

If you see that error somewhere else in your code not related totesting, it most likely indicates that you should move that code into aview function.

For information on how to use the request context from the interactivePython shell, seeWorking with the Shell.

How the Context Works

TheFlask.wsgi_app() method is called to handle each request. Itmanages the contexts during the request. Internally, the request andapplication contexts work like stacks. When contexts are pushed, theproxies that depend on them are available and point at information fromthe top item.

When the request starts, aRequestContext is created andpushed, which creates and pushes anAppContext first ifa context for that application is not already the top context. Whilethese contexts are pushed, thecurrent_app,g,request, andsession proxies are available to theoriginal thread handling the request.

Other contexts may be pushed to change the proxies during a request.While this is not a common pattern, it can be used in advancedapplications to, for example, do internal redirects or chain differentapplications together.

After the request is dispatched and a response is generated and sent,the request context is popped, which then pops the application context.Immediately before they are popped, theteardown_request()andteardown_appcontext() functions are executed. Theseexecute even if an unhandled exception occurred during dispatch.

Callbacks and Errors

Flask dispatches a request in multiple stages which can affect therequest, response, and how errors are handled. The contexts are activeduring all of these stages.

ABlueprint can add handlers for these events that are specificto the blueprint. The handlers for a blueprint will run if the blueprintowns the route that matches the request.

  1. Before each request,before_request() functions arecalled. If one of these functions return a value, the otherfunctions are skipped. The return value is treated as the responseand the view function is not called.

  2. If thebefore_request() functions did not return aresponse, the view function for the matched route is called andreturns a response.

  3. The return value of the view is converted into an actual responseobject and passed to theafter_request()functions. Each function returns a modified or new response object.

  4. After the response is returned, the contexts are popped, which callstheteardown_request() andteardown_appcontext() functions. These functions arecalled even if an unhandled exception was raised at any point above.

If an exception is raised before the teardown functions, Flask tries tomatch it with anerrorhandler() function to handle theexception and return a response. If no error handler is found, or thehandler itself raises an exception, Flask returns a generic500InternalServerError response. The teardown functions are stillcalled, and are passed the exception object.

If debug mode is enabled, unhandled exceptions are not converted to a500 response and instead are propagated to the WSGI server. Thisallows the development server to present the interactive debugger withthe traceback.

Teardown Callbacks

The teardown callbacks are independent of the request dispatch, and areinstead called by the contexts when they are popped. The functions arecalled even if there is an unhandled exception during dispatch, and formanually pushed contexts. This means there is no guarantee that anyother parts of the request dispatch have run first. Be sure to writethese functions in a way that does not depend on other callbacks andwill not fail.

During testing, it can be useful to defer popping the contexts after therequest ends, so that their data can be accessed in the test function.Use thetest_client() as awith block to preserve thecontexts until thewith block exits.

fromflaskimportFlask,requestapp=Flask(__name__)@app.route('/')defhello():print('during view')return'Hello, World!'@app.teardown_requestdefshow_teardown(exception):print('after with block')withapp.test_request_context():print('during with block')# teardown functions are called after the context with block exitswithapp.test_client()asclient:client.get('/')# the contexts are not popped even though the request endedprint(request.path)# the contexts are popped and teardown functions are called after# the client with block exits

Signals

The following signals are sent:

  1. request_started is sent before thebefore_request() functionsare called.

  2. request_finished is sent after theafter_request() functionsare called.

  3. got_request_exception is sent when an exception begins to be handled, butbefore anerrorhandler() is looked up or called.

  4. request_tearing_down is sent after theteardown_request()functions are called.

Notes On Proxies

Some of the objects provided by Flask are proxies to other objects. Theproxies are accessed in the same way for each worker thread, butpoint to the unique object bound to each worker behind the scenes asdescribed on this page.

Most of the time you don’t have to care about that, but there are someexceptions where it is good to know that this object is actually a proxy:

  • The proxy objects cannot fake their type as the actual object types.If you want to perform instance checks, you have to do that on theobject being proxied.

  • The reference to the proxied object is needed in some situations,such as sendingSignals or passing data to a backgroundthread.

If you need to access the underlying object that is proxied, use the_get_current_object() method:

app=current_app._get_current_object()my_signal.send(app)