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

Какие методы браузер может кэшировать?

2.0 Middle🔥 91 комментариев
#REST API и микросервисы

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

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

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

HTTP методы и кэширование браузера

Понимание того, какие HTTP методы браузер может кэшировать — это фундаментальное знание для разработчика, работающего с REST API и веб-приложениями. Это напрямую влияет на производительность и правильность приложения.

Методы, которые браузер МОЖЕТ кэшировать

GET — наиболее часто кэшируемый метод:

  • Браузер автоматически кэширует GET запросы
  • Использует HTTP headers для управления кэшем:
    • Cache-Control: max-age=3600
    • Expires: Wed, 21 Mar 2026 07:28:00 GMT
    • ETag для валидации кэша
    • Last-Modified для проверки изменений

Пример:

@GetMapping("/api/v1/users/{id}")
@CacheEvict(cacheNames = "users", key = "#id")
public ResponseEntity<UserDTO> getUser(@PathVariable String id) {
    return ResponseEntity.ok()
        .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS))
        .body(userService.findById(id));
}

HEAD — может быть кэширован

  • Идентичен GET по поведению кэширования
  • Не содержит body в ответе
  • Используется для проверки существования ресурса

OPTIONS — может быть кэширован

  • Браузер кэширует информацию о допустимых методах
  • Используется для CORS preflight запросов

Методы, которые браузер НЕ кэширует

POST — по умолчанию НЕ кэшируется:

  • Предназначен для создания новых ресурсов
  • Изменяет состояние сервера
  • Кэширование может привести к проблемам

Однако, возможно кэширование POST через явный заголовок (редко используется):

@PostMapping("/api/v1/search")
public ResponseEntity<List<SearchResult>> search(@RequestBody SearchQuery query) {
    // Если POST идемпотентный (например, поиск)
    return ResponseEntity.ok()
        .cacheControl(CacheControl.maxAge(5, TimeUnit.MINUTES))
        .body(searchService.search(query));
}

PUT — не кэшируется браузером

  • Используется для обновления существующих ресурсов
  • Побочные эффекты при кэшировании

DELETE — не кэшируется браузером

  • Удаляет ресурсы
  • Кэширование критически опасно

PATCH — не кэшируется браузером

  • Частичное обновление ресурса
  • Идентично PUT по рискам кэширования

Механизмы управления кэшем

Cache-Control header — главный инструмент:

  • public — может быть кэширован любым кэшем
  • private — только браузер (не shared caches)
  • no-cache — валидировать с сервером перед использованием
  • no-store — не кэшировать совсем
  • max-age=seconds — время жизни кэша
  • must-revalidate — после истечения переспросить сервер
@GetMapping("/api/v1/posts/{id}")
public ResponseEntity<PostDTO> getPost(@PathVariable String id) {
    return ResponseEntity.ok()
        .cacheControl(CacheControl.maxAge(1, TimeUnit.HOURS)
            .cachePublic()
            .mustRevalidate())
        .body(postService.findById(id));
}

ETag — условное кэширование:

  • Сервер генерирует хеш содержимого
  • Браузер проверяет: If-None-Match: "e4aff01234abcd1234"
  • Если не изменилось — ответ 304 Not Modified
@GetMapping("/api/v1/data")
public ResponseEntity<DataDTO> getData() {
    DataDTO data = dataService.getData();
    String etag = "\"" + data.hashCode() + "\"";
    
    return ResponseEntity.ok()
        .eTag(etag)
        .cacheControl(CacheControl.noCache())
        .body(data);
}

Last-Modified — временное кэширование:

  • Сервер указывает дату изменения ресурса
  • Браузер проверяет: If-Modified-Since: Wed, 21 Mar 2025 07:28:00 GMT
  • При совпадении — 304 Not Modified

Практические примеры

Кэшируемые ресурсы (GET):

  • Статические файлы (CSS, JS, изображения)
  • API ответы с исторических данных
  • Неизменяемые профили пользователей
  • Каталоги товаров

НЕ кэшируемые операции:

  • Аутентификация (POST /login)
  • Изменение профиля (PUT /profile)
  • Удаление ресурсов (DELETE)
  • Личные данные (кэш = security risk)

Кэширование в контексте микросервисов

В распределенной архитектуре:

@RestController
@RequestMapping("/api/v1/catalog")
public class ProductController {
    
    @GetMapping("/{id}")
    public ResponseEntity<ProductDTO> getProduct(@PathVariable String id) {
        // CDN может кэшировать это
        return ResponseEntity.ok()
            .cacheControl(CacheControl.maxAge(24, TimeUnit.HOURS).cachePublic())
            .body(productService.findById(id));
    }
    
    @PostMapping()
    public ResponseEntity<ProductDTO> createProduct(@RequestBody CreateProductRequest req) {
        // POST НЕ кэшируется (кроме явного указания)
        return ResponseEntity.created(uri).body(productService.create(req));
    }
    
    @PutMapping("/{id}")
    public ResponseEntity<ProductDTO> updateProduct(
            @PathVariable String id,
            @RequestBody UpdateProductRequest req) {
        // PUT не кэшируется
        // Должны инвалидировать кэш GET запроса
        productService.update(id, req);
        return ResponseEntity.ok().build();
    }
}

Инвалидация кэша

При изменении данных нужно инвалидировать кэш:

@PutMapping("/{id}")
@CacheEvict(cacheNames = "products", key = "#id")
public ResponseEntity<ProductDTO> updateProduct(
        @PathVariable String id,
        @RequestBody UpdateProductRequest req) {
    return ResponseEntity.ok(productService.update(id, req));
}

Заключение

В HTTP-спецификации:

  • GET, HEAD, OPTIONS могут быть кэшированы браузером
  • POST обычно не кэшируется (но технически может)
  • PUT, DELETE, PATCH не кэшируются

Напомню: правильное использование кэша требует понимания Cache-Control, ETag и Last-Modified headers. Это критически важно для оптимизации производительности приложения.