Files
changedetection.io/changedetectionio/tests
77fb923de6 fix(http): send a single Date header on werkzeug built-in server (#4372)
* fix(http): send a single Date header on werkzeug built-in server

Static resources served via werkzeug send_from_directory/send_file get a
Date header injected into the WSGI response by make_conditional()
(werkzeug/wrappers/response.py:752-757). When the app runs on Werkzeug's
built-in server -- the default path started through
socketio.run(..., allow_unsafe_werkzeug=True) in changedetectionio/__init__.py:694
and used by the docker entrypoint -- BaseHTTPRequestHandler.send_response()
(werkzeug/serving.py:271) emits its own Date header line as well, so the
wire response carries two Date headers. RFC 9110 forbids this and nginx
rejects the response with "upstream sent duplicate header line" (issue
#4299, see also #4101).

Fix: a global after_request hook pops the application-side Date copy so
only the server's single header reaches the wire. Verified safe on
gunicorn too, which also emits its own Date header.

Test: new tests/test_duplicate_date_header.py hits the live_server over
real HTTP with http.client (the Flask test client talks to the WSGI app
directly and never sees the server-added header) and asserts the Date
header appears exactly once, on the exact static resources named in the
issue. Fails on unfixed code with two identical Date lines; passes with
the fix.

Fixes #4299

* Apply suggestion from @dgtlmoon

* Tidy the #4299 Date header fix and its test

flask_app.py: the applied suggestion landed with a 3-space indent and
trailing whitespace - the latter was the only W291 in the file, which
.ruff.toml selects.

test_duplicate_date_header.py:
- drop the 10s socket wait loop, pytest-flask's live_server already
  blocks until the port accepts connections
- drop the unused `app` fixture argument (live_server depends on it)
- stop hardcoding jquery-3.6.0.min.js: asserting 200 on a vendored
  filename turns a jQuery bump into a failure in a file about HTTP
  headers. Any send_from_directory() response exercises the same path,
  so styles.css alone is enough.

Still red before the fix (two identical Date lines) and green after.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: dgtlmoon <leigh@morresi.net>
Co-authored-by: dgtlmoon <dgtlmoon@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-17 07:16:00 +02:00
..
…
…