$ time uv pip install -v --force-reinstall --index-url=http://localhost:9191/simple -r requirements.txt
some proxied requests that 304 are repeated without the etag to get a 200 response; uv logs this:
DEBUG Found modified response for: http://localhost:9191/resources/nwpy-awskms/nwpy_awskms-1.2.6-py3-none-any.whl.metadata
WARN Server returned unusable 304 for: http://localhost:9191/resources/nwpy-awskms/nwpy_awskms-1.2.6-py3-none-any.whl.metadata
"The server generating a 304 response MUST generate any of the following header fields that would have been sent in a 200 response to the same request: Content-Location, Date, Etag, Vary, ..., Cache-Control and Expires"
(and no others; Last-Modified is optional but useful). Date is always returned anyway, it's compulsory and uvicorn adds it. The others were not necessarily there in the 200 response; but Etag definitely must be, since that is how we can generate a response to an if-none-match.
So, minimally, we want to add etag to any 304 responses. Testing that, I added it in a few places - this one was for a TextResource in the router in simple.py:
If you run an install twice with uv, like:
some proxied requests that 304 are repeated without the etag to get a 200 response; uv logs this:
this relates to https://github.com/astral-sh/uv/issues/1754 where uv started making the second fetch because the 304 responses similarly were somehow "not valid".
Looking at one of these:
... there is a problem here. Reading the RFC: https://www.rfc-editor.org/rfc/rfc9110#name-304-not-modified
"The server generating a 304 response MUST generate any of the following header fields that would have been sent in a 200 response to the same request: Content-Location, Date, Etag, Vary, ..., Cache-Control and Expires"
(and no others; Last-Modified is optional but useful). Date is always returned anyway, it's compulsory and uvicorn adds it. The others were not necessarily there in the 200 response; but Etag definitely must be, since that is how we can generate a response to an if-none-match.
So, minimally, we want to add etag to any 304 responses. Testing that, I added it in a few places - this one was for a TextResource in the router in simple.py:
... and this works; uv no longer complained that the 304 is invalid and doesn't send a spurious extra request.