Можно ли модифицировать запросы в Retrofit
Что проверяют
Знаете ли вы, что Retrofit сам в сеть не ходит и все запросы проходят через OkHttp, и где правильно менять запрос: в сигнатуре метода или в клиенте. Следом почти всегда спрашивают, как вы обновляете истёкший токен.
Как отвечать
Модифицировать можно на трёх уровнях:
- аннотации метода:
@Path,@Query,@QueryMap,@Header,@HeaderMap, статические@Headers, тело через@Body, формы через@FormUrlEncodedи@Field, файлы через@Multipartи@Part. Адрес целиком подставляется на лету через@Url; - перехватчики OkHttp:
Interceptorберётchain.request(), делаетnewBuilder(), меняет заголовки, URL или тело и вызываетchain.proceed(). ЧерезaddInterceptor()добавляется перехватчик уровня приложения: он срабатывает один раз на вызов и видит исходный запрос. ЧерезaddNetworkInterceptor()добавляется сетевой: он срабатывает на каждый реальный запрос, включая редиректы, и видит итоговые заголовки; Authenticator: вызывается на ответ401, получает новый токен и возвращает повторный запрос. Для обновления токена это правильнее перехватчика.
Точечная настройка отдельных методов: Retrofit кладёт в запрос тег Invocation, перехватчик читает request.tag(Invocation::class.java) и по аннотации метода решает, добавлять ли авторизацию. Для логирования есть HttpLoggingInterceptor, уровень BODY включают только в debug-сборке.
Архитектурно: один OkHttpClient на приложение, варианты с другими таймаутами получают через newBuilder(), чтобы делить пул соединений. baseUrl у экземпляра Retrofit неизменяем, смену окружения решают через @Url, перехватчик, переписывающий хост, или отдельный экземпляр.
Где спотыкаются
Обновляют токен в обычном перехватчике без синхронизации. Пять параллельных запросов получают 401 и запускают пять обновлений, а при ротации refresh-токена сервер отзывает их друг за другом.
Оставляют HttpLoggingInterceptor с уровнем BODY в релизе. Токены и персональные данные уходят в logcat.
Создают новый OkHttpClient на каждый запрос или экран. Пропадает переиспользование соединений и HTTP-кэша, растут память и задержки.