Разработка REST API для мобильного приложения
REST API для мобильного приложения — это не просто набор эндпоинтов. Мобильный клиент работает в условиях, которых нет у веб-клиентов: нестабильное соединение, ограниченный трафик, многоверсионность (в App Store живут пользователи с версиями двухлетней давности). Это влияет на архитектурные решения с первого дня.
Проектирование под мобильный клиент
Гранулярность ответов. Классическая ошибка — эндпоинты, возвращающие слишком много данных. Экран профиля не должен тянуть весь объект пользователя с вложенными связями, если нужны только аватар и имя. BFF (Backend for Frontend) паттерн решает это: отдельный слой API, оптимизированный под мобильные экраны. Альтернатива — fields параметр в запросе (?fields=id,name,avatar).
Пагинация. Offset-based пагинация (?page=2&limit=20) не подходит для feeds в реальном времени — при добавлении новых записей смещение съезжает, пользователь видит дубли. Cursor-based пагинация (?after=eyJpZCI6MTIzfQ==) лишена этой проблемы. Обязательно возвращать hasMore флаг и nextCursor в ответе.
Версионирование API. Начинайте с версии в URL (/api/v1/). Мобильное приложение не обновляется принудительно — 15–20% пользователей остаются на старых версиях месяцами. v1 должна жить параллельно с v2 как минимум 6–12 месяцев.
Сетевой слой на клиенте
Android (Kotlin): Retrofit 2 + OkHttp + Kotlin Coroutines — устоявшийся стек. Interceptor в OkHttp для добавления Authorization заголовка, логирования (только в debug) и retry-логики:
class AuthInterceptor(private val tokenProvider: TokenProvider) : Interceptor {
override fun intercept(chain: Chain): Response {
val request = chain.request().newBuilder()
.addHeader("Authorization", "Bearer ${tokenProvider.getToken()}")
.build()
val response = chain.proceed(request)
if (response.code == 401) {
tokenProvider.refresh()
// retry с новым токеном
}
return response
}
}
iOS (Swift): URLSession нативно или Alamofire. Для типобезопасных запросов — Codable модели. RequestInterceptor в Alamofire для автоматического refresh токена аналогичен OkHttp Interceptor.
Flutter: dio пакет с Interceptor — логика та же. retrofit_dart генерирует типобезопасный клиент из аннотаций по аналогии с Retrofit.
Обработка ошибок
Структурированные коды ошибок важнее HTTP-статусов для клиентской логики:
{
"error": {
"code": "USER_NOT_FOUND",
"message": "User with specified ID does not exist",
"field": null
}
}
code — машиночитаемый, клиент делает switch по нему. message — для разработчика, не для пользователя. Клиент показывает свои локализованные строки по code, а не сырое message из API.
Валидационные ошибки должны возвращать field — название поля, которое не прошло проверку. Это позволяет подсвечивать конкретное поле в форме.
Кеширование и оффлайн
HTTP-кеширование через Cache-Control и ETag снижает нагрузку и ускоряет UX. OkHttp поддерживает HTTP-кеш из коробки с указанием директории и размера. Но для оффлайн-работы нужен отдельный слой: Room (Android) или CoreData/SwiftData (iOS) как локальная копия данных. Repository паттерн разделяет источники данных.
Безопасность
- Certificate Pinning:
OkHttp.CertificatePinnerна Android,URLSessionDelegateсdidReceive challengeна iOS. Усложняет MITM-атаки, но требует плана ротации сертификатов. - Не хранить JWT в
SharedPreferences(Android) илиUserDefaults(iOS). ИспользуйтеEncryptedSharedPreferences/Keychain. - HTTPS везде, без исключений. Никаких
cleartextв production.
Что входит в работу
Проектируем эндпоинты с учётом мобильной специфики, реализуем клиентский сетевой слой с interceptors, обработкой ошибок и retry, настраиваем кеширование. Документируем API через OpenAPI/Swagger для удобства мобильной команды.
Срок: 5–12 дней в зависимости от количества эндпоинтов и необходимости бэкенда.







