> В чем разница HTTP методов GET, POST, PUT, DELETE и когда их использовать (iOS, Swift)

Уровень: senior · Роль: mobile · Категория: Технические вопросы

Компании: Travelata

Стек: iOS, Swift

> Пример ответа

Короткий ответ

GET - для получения данных, идемпотентный и безопасный, не меняет состояние сервера. POST - для создания ресурса или выполнения действия с побочными эффектами, не идемпотентный. PUT - для полной замены ресурса по известному URI, идемпотентный. DELETE - для удаления ресурса, идемпотентный. В мобильной разработке выбор метода определяет семантику API, кэширование и обработку ошибок. Используйте GET для чтения, POST для создания, PUT для обновления целиком, DELETE для удаления.

Подробное объяснение

Основное различие лежит в семантике HTTP и гарантиях, которые каждый метод предоставляет.

GET

  • Безопасный: не изменяет состояние сервера.
  • Идемпотентный: повторные запросы дают тот же результат.
  • Поддерживает кэширование, условные запросы (If-Modified-Since, ETag).
  • Параметры передаются в query string или path.
  • В мобильных приложениях используется для загрузки списков, деталей, профилей.

POST

  • Не безопасный, не идемпотентный.
  • Создает новый ресурс или выполняет действие (например, аутентификация, поиск со сложными фильтрами).
  • Тело запроса содержит данные.
  • Ответ обычно 201 Created с Location заголовком.
  • В iOS часто используется для отправки форм, загрузки файлов, push-токенов.

PUT

  • Идемпотентный, но не безопасный.
  • Полная замена ресурса по известному URI.
  • Если ресурс не существует - может создать его (зависит от реализации).
  • Тело содержит полное представление ресурса.
  • В мобильной разработке применяется для обновления профиля, настроек, синхронизации.

DELETE

  • Идемпотентный, не безопасный.
  • Удаляет ресурс по URI.
  • Повторный DELETE возвращает 404 или 204, но состояние не меняется.
  • В мобильных приложениях - удаление сообщений, файлов, аккаунтов.

Ключевые отличия в контексте мобильной разработки:

  • Кэширование: GET кэшируется автоматически, остальные - нет.
  • Retry-логика: идемпотентные методы безопасно повторять при сетевых сбоях.
  • Тело запроса: GET не должен иметь body (хотя формально может), POST/PUT используют body.
  • URL-длина: GET ограничен длиной URL, POST - нет.

На практике

В iOS-приложениях выбор метода влияет на архитектуру сетевого слоя.

Типичные сценарии:

  • GET: загрузка ленты, профиля, истории заказов.
  • POST: регистрация, логин, создание поста, отправка сообщения.
  • PUT: обновление профиля, изменение настроек, синхронизация данных.
  • DELETE: удаление поста, выход из аккаунта (часто POST, но семантически DELETE).

Практические рекомендации:

  • Для мобильных клиентов используйте GET для всех операций чтения - это упрощает кэширование и работу с CDN.
  • POST используйте для действий, которые не вписываются в CRUD: оплата, отправка кода подтверждения.
  • PUT требует полного объекта - если обновляете частично, используйте PATCH (хотя вопрос про PUT, но это важно упомянуть).
  • При работе с Alamofire или URLSession проверяйте статус-коды: 200 для GET, 201 для POST, 200/204 для PUT/DELETE.
  • Учитывайте идемпотентность при реализации retry: для POST нужна защита от дублей (idempotency key).

Пример из практики: При реализации offline-режима: GET-запросы кэшируются на диске, POST ставятся в очередь и отправляются при восстановлении сети. PUT и DELETE требуют конфликт-резолюции, так как могут перезаписать более новые данные.

Пример кода

SWIFT
// Пример сетевого слоя на Swift с URLSession
enum HTTPMethod: String {
case get = "GET"
case post = "POST"
case put = "PUT"
case delete = "DELETE"
}
struct APIClient {
func request<T: Decodable>(
method: HTTPMethod,
path: String,
body: Encodable? = nil,
completion: @escaping (Result<T, Error>) -> Void
) {
var request = URLRequest(url: URL(string: "https://api.example.com\(path)")!)
request.httpMethod = method.rawValue
if let body = body {
request.httpBody = try? JSONEncoder().encode(body)
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
}
URLSession.shared.dataTask(with: request) { data, response, error in
// Обработка статус-кодов
guard let httpResponse = response as? HTTPURLResponse else {
completion(.failure(NetworkError.invalidResponse))
return
}
switch httpResponse.statusCode {
case 200...299:
guard let data = data else {
completion(.failure(NetworkError.noData))
return
}
do {
let decoded = try JSONDecoder().decode(T.self, from: data)
completion(.success(decoded))
} catch {
completion(.failure(error))
}
case 400...499:
completion(.failure(NetworkError.clientError(statusCode: httpResponse.statusCode)))
case 500...599:
completion(.failure(NetworkError.serverError(statusCode: httpResponse.statusCode)))
default:
completion(.failure(NetworkError.unexpectedStatusCode))
}
}.resume()
}
}
// Использование
let api = APIClient()
// GET
api.request(method: .get, path: "/users/123") { (result: Result<User, Error>) in
// обработка
}
// POST
let newPost = Post(title: "Hello", body: "World")
api.request(method: .post, path: "/posts", body: newPost) { (result: Result<Post, Error>) in
// обработка
}
// PUT
let updatedUser = User(id: 123, name: "New Name")
api.request(method: .put, path: "/users/123", body: updatedUser) { (result: Result<User, Error>) in
// обработка
}
// DELETE
api.request(method: .delete, path: "/posts/456") { (result: Result<EmptyResponse, Error>) in
// обработка
}

Как отвечать на собеседовании

Начните с краткого определения каждого метода, затем переходите к ключевым свойствам: безопасность и идемпотентность. Покажите понимание, как это влияет на реальную разработку.

Структура ответа:

  1. Определение каждого метода одной фразой.
  2. Сравнение по осям: безопасность, идемпотентность, кэширование.
  3. Примеры из мобильной практики.
  4. Упомяните PATCH как дополнение к PUT.
  5. Расскажите про обработку ошибок и статус-коды.

Для senior-позиции добавьте:

  • Рассуждение о дизайне API: когда POST вместо PUT, когда DELETE с телом.
  • Проблемы идемпотентности в реальных сценариях (повторная отправка формы).
  • Влияние на offline-синхронизацию и конфликты.

Что проверяет интервьюер

  • Понимание базовых принципов HTTP, а не заучивание определений.
  • Умение применять теорию к мобильной разработке.
  • Знание нюансов: идемпотентность, безопасность, кэширование.
  • Способность рассуждать о trade-off при выборе метода.
  • Понимание статус-кодов и их связи с методами.
  • Для senior - видение архитектурных последствий (retry, offline, синхронизация).

Типичные ошибки

  • Путаница между PUT и POST: часто говорят "PUT для обновления, POST для создания", но это упрощение - PUT может создавать, POST может обновлять.
  • Игнорирование идемпотентности: не упоминают, что повторный POST создаст дубль, а повторный DELETE безопасен.
  • Утверждение, что GET не может иметь body - формально может, но это плохая практика.
  • Забывают про PATCH, когда говорят о частичном обновлении.
  • Не связывают выбор метода с кэшированием - важный аспект для мобильных приложений.
  • Путают статус-коды: для POST ожидают 200, а не 201; для DELETE - 200 вместо 204.
  • Не учитывают ограничения URL для GET при передаче больших данных.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью