Что происходит при передаче несуществующего user id или выходе за допустимый диапазон
Что проверяют
Различаете ли вы «формат неверный» и «объект не найден», и доводите ли проверку до кода ответа и типа исключения. На бэкенде это вопрос про границы слоёв: где валидируется вход, где обращение к базе, где формируется ответ.
Как отвечать
Разложить на три случая, которые часто валят в один:
- идентификатор не того типа или формата, например строка вместо числа или сломанный UUID. Это ошибка запроса,
400, а с pydantic и FastAPI такой запрос до обработчика вообще не доходит и превращается в422с описанием поля; - идентификатор валидный, но пользователя с ним нет. Это
404, и обработчик обязан проверить результат сам: запрос в базу вернётNone, а не бросит исключение; - идентификатор валиден по формату, но вне допустимого диапазона: отрицательный или больше, чем помещается в колонку. У самого Python целые числа неограниченные, ограничение приходит от базы, и драйвер вернёт ошибку переполнения. Ловить её на уровне SQL плохо, диапазон описывают в схеме валидации, например через
Path(ge=1).
Полезно добавить про исключения: в доменном коде уместно своё исключение вроде UserNotFound, а превращение его в HTTP-ответ живёт в обработчике или общем перехватчике. Тогда бизнес-логика не знает про коды ответов, а формат ошибки одинаков на всех ручках.
Где спотыкаются
Отвечают 200 с пустым телом или с null вместо 404. Клиент не отличает «пользователя нет» от «пользователь без данных», и на экране появляется пустота без объяснения.
Второе: выпускают наружу необработанное исключение. Несуществующий идентификатор роняет обработчик, наружу уходит 500 со стектрейсом, а в нём имена таблиц и текст запроса. Ошибки ввода не должны доходить до пятисотых кодов.
Третье: не думают про перечисление пользователей. Если чужой идентификатор даёт 403, а несуществующий 404, по разнице ответов легко собрать список существующих. Там, где это важно, оба случая отвечают одинаково.