为什么 Flask 将此标头设置为“连接:关闭”?

Mag*_*nus 6 python flask

这是我的烧瓶代码,位于一个名为main.py-- 我试图让一个简单的服务器发送事件流运行的文件中:

import time
from flask import Flask, Response
from werkzeug.serving import WSGIRequestHandler

app = Flask(__name__)


def counter():
    i = 0
    while True:
        i = i+1
        yield "data: " + str(i) + "\n\n"
        time.sleep(1)


@app.route('/stream')
def send_message():
    return Response(
        counter(),
        mimetype='text/event-stream',
        headers={
            'Content-Type': 'text/event-stream',
            'Cache-Control': 'no-cache',
            'Connection': 'keep-alive',
            'Keep-Alive': 'timeout=55'
        }
    )


if __name__ == "__main__":
    WSGIRequestHandler.protocol_version = "HTTP/1.1"
    app.run(port=5001)
Run Code Online (Sandbox Code Playgroud)

当我运行此应用程序并python main.py在浏览器中打开它时,响应标头显示 BOTH Connection: keep-aliveAND Connection: close

在此输入图像描述

为什么会发生这种情况?如何让 Flask 只使用 keep-alive 标头?

小智 0

我刚刚在实现服务器发送事件 (SSE) 流时遇到了同样的问题(Flask 2.0.3 和 Python 3.6.8)。

Flask 使用 Werkzeug 库(在我的例子中是版本 2.0.3)。

在 Werkzeug 中,其响应写入函数“write”(在serving.py 的 WSGIRequestHandler.run_wsgi 中定义)在写入响应对象中的所有标头后有条件地写入“Connection: close”标头。

除非满足以下任一条件,否则会发生这种情况:

  1. 响应中存在“Content-Length”标头
  2. 请求方法是“HEAD”
  3. 响应状态码<200
  4. 响应状态码为204
  5. 响应状态码为304

重要的是,它不会检查响应对象是否已经具有“连接”标头,例如,如果您添加了自己的“连接”标头,就像您一样。

这就是 Flask 附加“Connection: close”标头的原因。

请注意,对于这个 SSE 用例,我认为上述所有 5 个条件都是错误的,这是正确的。特别是,状态代码应为 200,请求方法“GET”和“Content-Length”标头未指定。因此我认为这是 Werkzeug 中的一个错误,并且会针对它提出一个问题。