Goal: Instead of redirecting a client to a new path, the request should be redirected internally. The response should be returned without changing the clients (browser) URL.
The simplest way I found to achieve internal redirecting is by calling the app.full_dispatch_request
with a modified context.
def internal_redirect(path):
env = request.environ # take the original environment object
env['PATH_INFO'] = path # replace PATH_INFO with the new path
with landing.request_context(env): # push new request_context to stack
response = landing.full_dispatch_request() # handle original request with new path
return response
You could probably create more complex scenarios by manually pushing and popping the context.
env = request.environ # take the original environment object
env['PATH_INFO'] = path # replace PATH_INFO with the new path
ctx = landing.request_context(env) # create new request_context
ctx.push() # make new context active by pushing
response = some_view_function(foo='bar') # render view within original request but with new path
ctx.pop() # destroy new context
return response
This is my understanding of how Flask handles requests. Most of it comes from:
- The Flask
app
creates anapp.request_context(environ)
based on an environment variable that is passed from the WSGI server. - The
ctx = request_context()
is pushed to the request_context_stack viactx.push()
. Nowctx
is the currently active context. - The request is processed by the Flask
app
calling theapp.full_dispatch_request()
function (plus some error handling). - While
app.dispatch_request
would only call theview_function
,full_dispatch_request
also does the following:- Before each request,
before_request()
functions are executed. If one of these functions return a response, the other functions are no longer called. In any case however the return value is treated as a replacement for the view’s return value. - If the
before_request()
functions did not return a response, the regular request handling (app.dispatch_request
) kicks in and the view function that was matched has the chance to return a response. - The return value of the view is then converted into an actual response object and handed over to the
after_request()
functions which have the chance to replace it or modify it in place. - At the end of the request the
teardown_request()
functions are executed. This always happens, even in case of an unhandled exception down the road or if a before-request handler was not executed yet or at all (for example in test environments sometimes you might want to not execute before-request callbacks).
- Before each request,