Flask Test: preprocess_request(), dispatch_request()

Viewed 1197

My Environment:

Python3.7
Flask==1.0.2
pytest==4.3.1

I was looking for a method to retrieve both request object and response object in pytest function. And then I met across this unit testing snippet.

http://flask.pocoo.org/snippets/58/

and below is what I did.

def test_busking(session, monkeypatch, report=Report()):

    with app.test_request_context('/busking/zones'):
        # call the before funcs
        rv = app.preprocess_request()
        if rv != None:
            response = app.make_response(rv)
        else:
            # do the main dispatch
            rv = app.dispatch_request()
            response = app.make_response(rv)

            # now do the after funcs
            response = app.process_response(response)

        assert flask.request
        assert response

It works well In my environment. I was able to get both objects. What my questions are...

  • dispatch_request() is called when only rv is None. why not when rv is something else?

  • process_response() also called when rv is None why is that?

  • it seams like preprocess_request() calls before_request_funcs and rv is the return value of the last before_request_function... it looks like rv has nothing to do with dispatching request please but I know It has to be something... tell me what I'm wrong about.

There are still tons of things I don't understand in preprocess_request(), make_response(), dispatch_request(), process_response(). I think rv and process_request() are playing great roles but I'm not sure. I would be more than greatful if you also explain what is going on background.

1 Answers

I'm not an expert in Flask, so this answer might miss some points, but I think it's enough to help clarify your situation:

  • If a before_request function returns something else than None, it is taken as the view's response, so no more treatment happens, see preprocess_request's doc
  • process_response calls the after_request methods, it's called regardless of the response content (AFAIK)
  • As per the same doc linked above, I would say that rv is the first non-None result received from before_request, not the last, as as soon as a non-None is returned, the processing stops.

At a glance, I would say that this is the order of things:

  1. preprocess_request: call the before_request functions in order
  2. As soon as one of them returns something different than None, stop calling the remaining ones and jump to (4)
  3. dispatch_request: call the method associated to the routing rule
  4. make_response: prepare the Response object based on the previous result (here, rv)
  5. process_response: call the after_request functions with the Response object
Related