Запрос с кириллицей падал с 500, хотя тесты на английском проходили

Сервис принимал имя пользователя через @RequestParam, валидировал длину и сохранял в базу. На стейдже с тестовыми данными на латинице всё работало. На проде первые же запросы с именами на кириллице стали падать с 500 без внятной причины в логе.

Проблема была в валидации — регулярка на длину строки считала не символы, а байты UTF-8 после неявного преобразования в byte[] где-то в цепочке фильтров. Кириллица в UTF-8 — два байта на символ, значит строка в 20 символов превращалась в 40 байт и упиралась в лимит, рассчитанный под латиницу.

Починили заменой байтового лимита на String.codePointCount() — считает символы, а не байты, и корректно работает с суррогатными парами, которых кириллица не использует, но эмодзи в будущем использовали бы.

int length = username.codePointCount( 0, username.length() );

if (length > MAX_LENGTH) { throw new ValidationException( "Name too long" ); }

На ревью спросили: а что будет, если в строке есть эмодзи с ZWJ-последовательностью — несколько code point визуально выглядят одним символом. codePointCount их всё равно посчитает отдельно, то есть смайлик из трёх code point даст длину 3, а не 1. Для лимита на UI это может быть неточно, но для защиты от переполнения буфера — достаточно.

Тесты на латинице не ловят баги кодировки — проверяйте граничные случаи на реальном алфавите продакшена.

Тренажёр: 907 вопросов, мок с таймером, план повторов

senior·base — что спрашивают на самом деле


В этом посте были ссылки, но мы их удалили по правилам Сетки