sanic
sanic copied to clipboard
Raising a 412 on a Sanic handler causes a wait period and maybe a ReadTimeout exception on clients
Describe the bug
When raising a 412, clients are left waiting to read until a timeout is triggered and a ReadTimeout exception may occur.
Code snippet
The issue can be reproduced with code for an app as minimal as:
# Server Side
from sanic import Sanic
from sanic import exceptions
app = Sanic("MyHelloWorldApp")
@app.get('/hello')
async def hello_world(request, *args, **kwargs):
raise exceptions.SanicException('Failed Precondition', status_code=412)
if __name__ == '__main__':
app.run()
The client can be Postman, bash curl, or even a Python fetch:
# Client Side
import asyncio
import time
import httpx
async def async_fetch():
async with httpx.AsyncClient() as client:
return await client.get('http://localhost:8000/hello')
if __name__ == '__main__':
now = time.time()
try:
resp = asyncio.get_event_loop().run_until_complete(async_fetch())
except Exception as e:
print('Exception:', type(e))
else:
print('Response:', resp)
finally:
print('Time:', time.time() - now)
The above client code will print:
Exception: <class 'httpx.ReadTimeout'>
Time: 5.057372808456421
Expected behavior
The client should quickly receive the 412 response.
Environment (please complete the following information):
- OS: macOS Monterey with M1 chip
- Sanic Version: 22.9.0
Additional context
What I think is happening is that Sanic strips the headers on 412 responses, including the content-type
header. However, and contrary to what happens for a 304 code, Sanic will still send the 412 response body to the client, which causes the latter to wait for more data, without knowing the actual size of the response, until it times out.