FastAPI + uvicorn: как перехватить исключение в процессе websocket handshake?
Добрый день.
Не могу найти вариант перехвата исключения при websocket handshake.
Проект с реализацией API на FastAPI, работает с программно запускаемым uvicorn ( uvicorn.run() )
Беда вылезает, когда подключается клиент с некорректной кукой - не ascii-символы в теле куки.
Сервер выдает в консоль исключение и на какое то время перестает обслуживать запросы.
Хотелось бы перехватить это исключение, отлогировать ip клиента и продолжить работу, но не могу найти способ перехватить ошибку.
Исключение выдает именно uvicorn, до fastapi дело еще даже не дошло...
Как минимум, запусти дебаггер, напиши юнит-тест, воспроизводящий ошибку и лови это исключение им. Да и кто тебя знает, используешь ты в коде WebSocketEndpoint или сам низкоуровневый объект WebSocket.
В том то и дело, что исключение возникает не в моем коде, а в коде uvicorn. Причина исключения - некорректно сформированный заголовок в запросе клиента.
Ищу защиту от таких ситуаций. Последнее направление, в котором сейчас ищу - перед uvicorn стоит nginx и отбрасывает таких клиентов.
В трасировке исключения ссылка как раз на разбор заголовков:
Error in opening handshake
Traceback (most recent call last):
File "/usr/local/lib/python3.7/site-packages/websockets/server.py", line 134, in handler
extra_headers=self.extra_headers,
File "/usr/local/lib/python3.7/site-packages/websockets/server.py", line 532, in handshake
early_response = await early_response_awaitable
File "/usr/local/lib/python3.7/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 98, in process_request
for name, value in headers.raw_items()
File "/usr/local/lib/python3.7/site-packages/uvicorn/protocols/websockets/websockets_impl.py", line 98, in <listcomp>
for name, value in headers.raw_items()
UnicodeEncodeError: 'ascii' codec can't encode characters in position 241-254: ordinal not in range(128)
Так как не владею в нужной мере uvicorn то единственное что могу посоветовать это искать фрагмент import'a websockets/server.py в инициализацию сервера либы uvicorn. и пробросить изменения метода process_request класса, который описан в websockets_impl.py. Ну или модифицировать код либы не через наследование тогда это конечно костыль (=.