Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Connection: close" added to response in SSE use-case #2759

Closed
chrisvroberts opened this issue Aug 7, 2023 · 1 comment
Closed

"Connection: close" added to response in SSE use-case #2759

chrisvroberts opened this issue Aug 7, 2023 · 1 comment

Comments

@chrisvroberts
Copy link

chrisvroberts commented Aug 7, 2023

"Connection: close" is appended to the HTTP response by wekzeug despite the client code having already added the "Connection: keep-alive" header.

I am using werkzeug to implement a Server-Sent-Event (SSE) stream (see https://html.spec.whatwg.org/multipage/server-sent-events.html). In this use-case:

  • the request method is a GET;
  • the response status code should be 200; and
  • the response content length is not known and therefore the 'Content-Length' header is not in the response.

Despite setting the "Connection: keep-alive" header on the response object, werkzeug still appends an additional "Connection" header to the response: "Connection: close".

The "write" function in WSGIRequestHandler.run_wsgi makes as number of checks before adding the extra header, but for the SSE use-case none of them prevent the extra header being added.

Specifically it will add the header unless any one of the following conditions are true:

  • the 'Content-Length' header is present in the response
  • the request method was 'HEAD'
  • the response status code is <200
  • the response status code is 204
  • the response status code is 304

For SSE I don't think any of these are true but the it should still be possible for a user to set the "Connection" header value to "keep-alive".

Since SSE is a standard use-case I think this is a bug.

Arguably an extra check could be added so that the "Connection: close" header is not added if a "Connection" header already exists on the response object?

 1 from flask import Flask, Response
 2 from datetime import datetime
 3 from time import sleep
 4
 5 app = Flask(__name__)
 6
 7 @app.route('/')
 8 def root():
 9     def generate():
10         while True:
11             sleep(1)
12             yield 'data: ' + str(datetime.now()) + '\r\n\r\n'
13     response = Response(generate(), mimetype='text/event-stream')
14     response.headers['Connection'] = 'keep-alive'
15     return response

I would expect the response to have a single "Connection" header with value "keep-alive" but instead to has two:

  • "Connection: keepalive" (added by the client code); and
  • "Connection: close" (added by werkzeug).

Environment:

  • Python version: 3.6.8
  • Flask version: 2.0.3
  • Werkzeug version: 2.0.3
@davidism
Copy link
Member

davidism commented Aug 7, 2023

I can't reproduce your requirement. SSE works fine without setting the Connection header. The page you've linked to describing SSE does not mention keep-alive.

The application can't set the Connection header, because the application is not the server, and the server controls what HTTP features it supports. HTTP/1.1 keep-alive is not handled well by Python's http.server, so it's not enabled. There's a long comment explaining this right above the code you wrote about.

If you need keep-alive, you can use a production WSGI server such as Gunicorn.

@davidism davidism closed this as not planned Won't fix, can't repro, duplicate, stale Aug 7, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Aug 22, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants