← Назад к вопросам

Что делает PATCH в REST?

1.2 Junior🔥 191 комментариев
#ASP.NET и Web API

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое HTTP PATCH в REST

В RESTful архитектуре PATCH — это метод HTTP запроса, который предназначен для частичного обновления ресурса. Он является частью стандарта HTTP/1.1 и играет ключевую роль в эффективном взаимодействии клиента и сервера.

Ключевые особенности PATCH

  • Частичное обновление: Основное отличие от метода PUT, который обычно требует полного замещения ресурса, заключается в том, что PATCH позволяет передать только те изменения, которые необходимо внести в существующий ресурс. Это повышает эффективность и снижает нагрузку на сеть.
  • Семантика запроса: Клиент отправляет на сервер набор инструкций (или "патч"), описывающих, как модифицировать ресурс. Сервер применяет эти инструкции к текущему состоянию ресурса.
  • Идемпотентность: В соответствии с HTTP стандартом (RFC 5789), PATCH не является строго идемпотентным. Несколько одинаковых PATCH запросов могут привести к разному конечному состоянию ресурса (например, если патч содержит команду "увеличить значение на 5").

Сравнение с PUT

Чтобы понять разницу, рассмотрим пример ресурса User.

// Исходное состояние ресурса на сервере (GET /users/1)
{
    "id": 1,
    "name": "Иван",
    "email": "ivan@example.com",
    "age": 30,
    "city": "Москва"
}

Если мы хотим обновить только email, используя разные методы:

PUT запрос требует передачи всего ресурса, даже неизменных полей:

PUT /users/1
Content-Type: application/json

{
    "id": 1,
    "name": "Иван", // Эти данные повторно отправляются
    "email": "ivan.new@domain.com", // Только это поле меняется
    "age": 30, // Эти данные повторно отправляются
    "city": "Москва" // Эти данные повторно отправляются
}

PATCH запрос позволяет передать только изменения:

PATCH /users/1
Content-Type: application/json

{
    "email": "ivan.new@domain.com" // Только измененное поле
}

Или, используя более формальный патч-формат (например, JSON Patch):

PATCH /users/1
Content-Type: application/json-patch+json

[
    { "op": "replace", "path": "/email", "value": "ivan.new@domain.com" }
]

Форматы данных для PATCH

Для описания изменений используются различные форматы. Самые распространенные:

  1. Простой JSON (де факто стандарт): Клиент отправляет объект только с изменяемыми полями. Сервер интерпретирует это как инструкцию "заменить значения этих полей на предоставленные".

    { "email": "new@mail.com", "age": 31 }
    
  2. JSON Patch (RFC 6902): Специальный стандартизированный формат, который описывает операции (op) над ресурсом: add, remove, replace, move, copy, test.

    [
        { "op": "replace", "path": "/email", "value": "new@mail.com" },
        { "op": "replace", "path": "/age", "value": 31 }
    ]
    
  3. JSON Merge Patch (RFC 7396): Упрощенный формат, где отправляется часть JSON документа. Все присутствующие поля заменяются, а поле со значением null означает его удаление.

    { "email": "new@mail.com", "age": 31, "city": null }
    

Реализация PATCH в C# Backend (ASP.NET Core)

В ASP.NET Core для обработки PATCH часто используют подход с JsonPatchDocument<T> из пакета Microsoft.AspNetCore.JsonPatch.

// Пример контроллера
[HttpPatch("{id}")]
public async Task<IActionResult> PatchUser(int id, [FromBody] JsonPatchDocument<UserDto> patchDoc)
{
    // 1. Получаем существующий ресурс из базы данных
    var userEntity = await _repository.GetByIdAsync(id);
    if (userEntity == null)
        return NotFound();

    // 2. Преобразуем Entity в DTO (или работаем напрямую с моделью)
    var userDto = _mapper.Map<UserDto>(userEntity);

    // 3. Применяем патч к DTO
    patchDoc.ApplyTo(userDto);

    // 4. Проверяем валидность модели после применения патча
    if (!TryValidateModel(userDto))
        return BadRequest(ModelState);

    // 5. Обновляем Entity данными из DTO и сохраняем
    _mapper.Map(userDto, userEntity);
    await _repository.UpdateAsync(userEntity);

    // 6. Возвращаем обновленный ресурс
    return Ok(_mapper.Map<UserDto>(userEntity));
}

Преимущества использования PATCH

  • Эффективность передачи данных: Снижает объем трафика, особенно для крупных ресурсов.
  • Уменьшение вероятности конфликтов: Клиент может точно указать, что меняет, что полезно в системах с параллельными изменениями.
  • Более тонкий контроль: Поддерживает сложные операции (удаление, добавление элементов в массивы) через JSON Patch.

Вопросы безопасности и валидации

При использовании PATCH необходимо уделять особое внимание:

  • Валидации частичных данных: Сервер должен проверять корректность только обновляемых полей в контексте всего ресурса.
  • Обработке ошибок: Нужно четко указывать, если патч не может быть применен (например, некорректный путь path в JSON Patch).
  • Идемпотентности: Для критических операций иногда лучше использовать PUT или реализовывать механизмы, обеспечивающие идемпотентность PATCH (например, с помощью условных заголовков If-Match).

Заключение

PATCH является мощным и специализированным инструментом в REST API для выполнения частичных обновлений. Его правильное использование повышает эффективность API, снижает нагрузку и предоставляет клиентам более гибкий интерфейс. Однако, его реализация требует внимательности от разработчика backend, особенно в вопросах валидации, безопасности и четкого определения семантики изменений для клиентов API. В современных C# приложениях с ASP.NET Core это достигается через использование JsonPatchDocument и тщательное проектирование логики применения изменений.