'Flask 405 error with valid route when not accessing request data

I'm getting a 405 error when I don't actually use a request body for successive identical requests.

Example:

app = Flask(__name__)
CORS(app)
    
@app.route("/login", methods=["POST"])
def login():
    return jsonify({'success': True})

Request body is pretty simple:

{'username': 'foo', 'password': 'bar'}

Flutter code generating request:

http.Response response = await http.post(
      Uri.parse("http://127.0.0.1:5000/login"),
      headers: <String, String>{
        'Content-Type': 'application/json; charset=UTF-8',
      },
      body: jsonEncode(<String, String>{
        'username': username,
        'password': username,
      }),
    );

Term output:

127.0.0.1 - - [10/May/2022 05:37:36] "OPTIONS /login HTTP/1.1" 200 -
127.0.0.1 - - [10/May/2022 05:37:36] "POST /login HTTP/1.1" 200 -
127.0.0.1 - - [10/May/2022 05:37:41] "{"username":"foo","password":"bar"}POST /login HTTP/1.1" 405 -
127.0.0.1 - - [10/May/2022 05:37:55] "{"username":"foo","password":"bar"}OPTIONS /login HTTP/1.1" 405 -

This is greatly simplified, but is enough to produce the expected error.

However, this Flask code does not generate the same error:

@app.route("/login", methods=["POST"])
def login():
    print(request.json['username'])
    return jsonify({'success': True})

And term output:

127.0.0.1 - - [10/May/2022 05:58:54] "POST /login HTTP/1.1" 200 -
127.0.0.1 - - [10/May/2022 06:08:16] "OPTIONS /login HTTP/1.1" 200 -
foo
127.0.0.1 - - [10/May/2022 06:08:16] "POST /login HTTP/1.1" 200 -
foo
127.0.0.1 - - [10/May/2022 06:08:16] "POST /login HTTP/1.1" 200 -
foo

I realize this is a stupid scenario, because when wouldn't you actually use the data? I just ran into this while tinkering and lost an hour figuring out why it was throwing the error.

My question is: Why does it throw a 405 error and what is the actual difference? Does the data persist between requests if you don't access it? Is this intended functionality, and is there documentation that covers this?



Solution 1:[1]

This was fixed in Werkzeug 2.1.2: https://github.com/pallets/werkzeug/issues/2397

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 davidism