Why does my Flask app return a response with status code 308 under test?

Viewed 576

I'm unit testing my Flask app. The code under test is as follows:

@app.route("/my_endpoint/", methods=["GET"])
def say_hello():
    """
    Greets the user.
    """
    name = request.args.get("name")
    return f"Hello {name}"

The test looks like this:

class TestFlaskApp:
    def test_my_endpoint(self):
        """
        Tests that my endpoint returns the result as plain text.
        :return:
        """
        client = app.test_client()
        response = client.get("/my_endpoint?name=Peter")
        assert response.status_code == status.HTTP_200_OK
        assert response.data.decode() == "Hello Peter"

The error is:

Expected :200 Actual :308

So instead of "OK" (200) I'm getting a "Permanent Redirect" (308)

2 Answers

If the @app.route ends with a slash you must also use the slash in the test: Instead of

response = client.get("/my_endpoint?name=Peter")

use

response = client.get("/my_endpoint/?name=Peter")

in your unit test.

It makes sense yet took me too long time to find out.

Flask use werkzeug.routing.Rule, which enable strict_slashes as default, visiting a branch URL without a trailing slash will redirect to the URL with a slash appended. Which cause response with 308 (Permanent Redirect).

So, your request path must be exactly matched with the route path.

If you want to support both routes:

  • /my_endpoint
  • /my_endpoint/

Just set app.route with strict_slashes=False, like this:

@app.route('/my_endpoint', methods = ['POST'], strict_slashes=False)
def view_func():
    pass
Related