Зачем ограничивать тело запроса в Retrofit
Что проверяют
Понимаете ли вы, что тело запроса на мобильном устройстве упирается сразу в память, сеть и ограничения сервера. Следом обычно просят рассказать, как загрузить большой файл через Retrofit и не получить OutOfMemoryError.
Как отвечать
Ограничивать тело приходится по нескольким причинам, и у каждой свой приём:
- память: конвертер Gson, Moshi или kotlinx.serialization сериализует объект в память целиком. Синхронизация тысяч записей одним запросом создаёт большой буфер и нагрузку на сборщик мусора, поэтому отправляют пачками фиксированного размера;
- файлы: картинку или видео не читают в
ByteArray. Тело строят из файла черезfile.asRequestBody(mediaType), и OkHttp стримит его в сокет частями, а в интерфейсе используют@MultipartсMultipartBody.Part. Фото перед отправкой сжимают и уменьшают; - лимит сервера: у nginx по умолчанию
client_max_body_sizeравен 1 МБ, на больший запрос придёт413 Payload Too Large. Размер лучше проверить на клиенте до отправки и показать понятную ошибку; - мобильная сеть: большой запрос на плохом канале упирается в таймауты OkHttp (по умолчанию 10 секунд на соединение, чтение и запись) и при обрыве начинается заново. Для больших файлов используют загрузку частями с докачкой, например multipart upload в S3-совместимое хранилище по подписанным ссылкам, а саму загрузку отдают в WorkManager, чтобы она пережила уход приложения в фон;
- логирование:
HttpLoggingInterceptorна уровнеBODYчитает тело в память ради лога и пишет в Logcat персональные данные. В релизной сборке уровень должен бытьNONEилиBASIC; - лишние поля: отправляйте DTO под конкретный запрос, а не всю доменную модель пользователя.
Где спотыкаются
Путают тему с @Streaming. Эта аннотация относится к телу ответа при скачивании, на отправку она не влияет.
Читают файл через readBytes() и заворачивают массив в RequestBody. На устройстве с небольшой кучей видео в сотни мегабайт почти гарантированно уронит приложение.
Оставляют Level.BODY включённым в проде. Помимо утечки токенов и паролей в лог, интерцептор копирует в память каждый загружаемый файл целиком.