Ответ
Согласно спецификации HTTP, безопасными (safe) считаются методы, которые не должны изменять состояние сервера. Они предназначены только для получения данных. К ним относятся:
GET— для получения ресурса.HEAD— аналогичен GET, но сервер возвращает только заголовки ответа без тела.OPTIONS— для получения поддерживаемых методов для ресурса.TRACE— для диагностики (используется редко).
Важность для тестирования безопасности и корректности API:
-
Идемпотентность и побочные эффекты: В тестах я всегда проверяю, что безопасные методы действительно не вносят изменений. Например, многократный вызов
GET /api/usersне должен создавать новых пользователей, списывать средства или блокировать аккаунты. Это проверяется сравнением состояния системы до и после серии запросов. -
Кэширование: Безопасные методы, в частности
GET, по умолчанию подлежат кэшированию. При тестировании я проверяю, что API возвращает корректные заголовки кэширования (Cache-Control,ETag), и что кэшированные данные не приводят к отображению устаревшей или конфиденциальной информации другого пользователя. -
Безопасность: С точки зрения безопасности,
GET-запросы не должны использоваться для операций, меняющих состояние, так как их параметры остаются в истории браузера, логах и могут передаваться по ссылке. В тестах я специально пытаюсь отправить данные, которые должны передаваться черезPOST(например, credentials), методомGETи ожидаю, что сервер отклонит такой запрос или будет обрабатывать его безопасно.
Пример теста, проверяющего безопасность GET-запроса:
@Test
public void get_request_should_not_create_resource() {
// Запоминаем начальное состояние
int initialUserCount = userService.getAllUsers().size();
// Пытаемся выполнить GET с параметрами, похожими на создание
Response response = given()
.queryParam("name", "Hacker")
.queryParam("email", "hack@test.com")
.when()
.get("/api/users"); // НЕПРАВИЛЬНЫЙ дизайн API, если так можно создать
// Проверяем, что запрос завершился успешно (для получения данных), но НЕ создал сущность
assertThat(response.statusCode()).isEqualTo(200);
assertThat(userService.getAllUsers().size())
.as("GET request should not change state")
.isEqualTo(initialUserCount);
}
Понимание семантики безопасных методов — основа для проектирования корректных REST API и написания точных тестов на их безопасность и надёжность.