Issue 1:
A tiny Flask app with a PUT request is behaving strangely: after it sends the response body that it is supposed to send (from my code), it then sends a second response body with a Flask error in it. The core of the error response is "Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method."

It looks as though something is parsing the PUT request body as the beginning of a second HTTP request on the same TCP connection.

Here is my app to reproduce the problem (`flaskdouble.py):

import flask

app = flask.Flask('flaskdouble')

@app.route('/foo', methods=['PUT', 'POST'])
def foo():
return 'simple response\n'

I'm running it in a Flask working dir, on the 2.1.x branch:

FLASK_APP=flaskdouble FLASK_ENV=development ./env/bin/flask run --port 4080

To see the problem, I needed to attach a packet sniffer to the connection. For example, ngrep can do it with

sudo ngrep -d lo -W byline port 4080

Now with both flaskdouble.py and ngrep running, send a request to it:

curl -v -X PUT -H 'content-type: text/plain' -d 'hello' http://localhost:4080/foo
* Trying 127.0.0.1:4080...
* Connected to localhost (127.0.0.1) port 4080 (#0)
> PUT /foo HTTP/1.1
> Host: localhost:4080
> User-Agent: curl/7.74.0
> Accept: */*
> content-type: text/plain
> Content-Length: 5
>
* upload completely sent off: 5 out of 5 bytes
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: Werkzeug/2.1.1 Python/3.9.7
< Date: Sat, 16 Apr 2022 00:10:10 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 16
<
simple response
* Connection #0 to host localhost left intact

That looks fine ... until we look at the traffic captured by ngrep:

####
T 127.0.0.1:56228 -> 127.0.0.1:4080 [AP] #42
PUT /foo HTTP/1.1.
Host: localhost:4080.
User-Agent: curl/7.74.0.
Accept: */*.
content-type: text/plain.
Content-Length: 5.
.
hello
##
T 127.0.0.1:4080 -> 127.0.0.1:56228 [AP] #44
HTTP/1.1 200 OK.
Server: Werkzeug/2.1.1 Python/3.9.7.
Date: Sat, 16 Apr 2022 00:10:10 GMT.
Content-Type: text/html; charset=utf-8.
Content-Length: 16.
.

##
T 127.0.0.1:4080 -> 127.0.0.1:56228 [AP] #46
simple response

###
T 127.0.0.1:4080 -> 127.0.0.1:56228 [AP] #49
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
<title>Error response</title>
</head>
<body>
<h1>Error response</h1>
<p>Error code: 400</p>
<p>Message: Bad request syntax ('hello').</p>
<p>Error code explanation: HTTPStatus.BAD_REQUEST - Bad request syntax or unsupported method.</p>
</body>
</html>

#^Cexit
50 received, 16 matched

The logging emitted by my flaskdouble app is also curious:

127.0.0.1 - - [15/Apr/2022 20:13:11] "PUT /foo HTTP/1.1" 200 -
127.0.0.1 - - [15/Apr/2022 20:13:11] code 400, message Bad request syntax ('hello')
127.0.0.1 - - [15/Apr/2022 20:13:11] "None /foo HTTP/0.9" HTTPStatus.BAD_REQUEST -

Expected behaviour:

the app should write exactly 16 bytes to its client, namely "simple response\n". That second response body, an HTML error document, should not be there.

the app should log exactly one line, namely "PUT /foo HTTP/1.1" 200 -

Environment:

Python version: 3.9.7

Flask version: 2.1.1-12-g2b8b4781 (in a git working dir)

My virtualenv is barebones:

./env/bin/pip freeze
click==8.1.2
-e git+ssh://git@github.com/pallets/flask.git@2b8b47817a981b97a233420b5214f6ff9e771c35#egg=Flask
importlib-metadata==4.11.3
itsdangerous==2.1.2
Jinja2==3.1.1
MarkupSafe==2.1.1
pkg_resources==0.0.0
Werkzeug==2.1.1
zipp==3.8.0

Issue 2:
With the following example:

from flask import Flask

app = Flask(__name__)

@app.route('/', methods=['POST'])
def hello_world():
return 'Hello World!'

if __name__ == '__main__':
app.run()

When you set the request body to {} with Postman or any HTTP clients, the first request will return 200, while the second request will return a 405 error response. The log shows the request method is {}POST:

"{}POST / HTTP/1.1" 405

Notice the request body became the part of the request method.