Какие знаешь типы запросов REST?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Типы запросов REST (HTTP методы)
REST — архитектурный стиль, использующий стандартные HTTP методы для операций над ресурсами. Каждый метод имеет чётко определённую семантику и применение.
1. GET (Получить ресурс)
GET — безопасный, идемпотентный метод для получения данных без изменений на сервере.
// GET /api/users → Получить список всех пользователей
GET /api/users
Response: [
{"id": 1, "name": "John", "email": "john@example.com"},
{"id": 2, "name": "Jane", "email": "jane@example.com"}
]
Status: 200 OK
// GET /api/users/1 → Получить конкретного пользователя
GET /api/users/1
Response: {"id": 1, "name": "John", "email": "john@example.com"}
Status: 200 OK
// GET /api/users?age=30&city=NYC → С параметрами (Query string)
GET /api/users?age=30&city=NYC
Response: [...отфильтрованные пользователи...]
Status: 200 OK
REST контроллер
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping // GET /api/users
public ResponseEntity<List<UserDTO>> getAllUsers(
@RequestParam(required = false) Integer age,
@RequestParam(required = false) String city) {
List<UserDTO> users = userService.findUsers(age, city);
return ResponseEntity.ok(users);
}
@GetMapping("/{id}") // GET /api/users/1
public ResponseEntity<UserDTO> getUserById(@PathVariable Long id) {
UserDTO user = userService.findById(id)
.orElseThrow(() -> new ResourceNotFoundException("User not found"));
return ResponseEntity.ok(user);
}
}
2. POST (Создать ресурс)
POST — небезопасный, неидемпотентный метод для создания новых ресурсов.
// POST /api/users → Создать нового пользователя
POST /api/users
Body: {
"name": "John",
"email": "john@example.com",
"age": 30
}
Response: {
"id": 3,
"name": "John",
"email": "john@example.com",
"age": 30
}
Status: 201 Created
Location: /api/users/3
REST контроллер
@RestController
@RequestMapping("/api/users")
public class UserController {
@PostMapping // POST /api/users
public ResponseEntity<UserDTO> createUser(@RequestBody CreateUserRequest request) {
UserDTO created = userService.create(request);
// ✅ Возвращаем 201 Created с Location заголовком
return ResponseEntity
.created(URI.create("/api/users/" + created.getId()))
.body(created);
}
}
Идемпотентность POST
// ❌ POST не идемпотентен (каждый вызов создаёт новый ресурс)
POST /api/users {name: "John"} // Создаёт пользователя с id=1
POST /api/users {name: "John"} // Создаёт пользователя с id=2 (дублирование!)
// ✅ Решение: используй PUT или добавь check for existence
3. PUT (Заменить ресурс полностью)
PUT — небезопасный, но идемпотентный метод для замены целого ресурса. Идемпотентность гарантируется тем, что повторный запрос даст тот же результат.
// PUT /api/users/1 → Заменить всего пользователя
PUT /api/users/1
Body: {
"name": "John Updated",
"email": "john.updated@example.com",
"age": 31
}
Response: {
"id": 1,
"name": "John Updated",
"email": "john.updated@example.com",
"age": 31
}
Status: 200 OK или 204 No Content
REST контроллер
@RestController
@RequestMapping("/api/users")
public class UserController {
@PutMapping("/{id}") // PUT /api/users/1
public ResponseEntity<UserDTO> updateUser(
@PathVariable Long id,
@RequestBody UpdateUserRequest request) {
UserDTO updated = userService.update(id, request);
return ResponseEntity.ok(updated);
}
}
Идемпотентность PUT
// ✅ PUT идемпотентен
PUT /api/users/1 {name: "John"} // Обновляет на "John"
PUT /api/users/1 {name: "John"} // Снова "John" (тот же результат)
PUT /api/users/1 {name: "John"} // Снова "John" (тот же результат)
4. PATCH (Частичное обновление)
PATCH — небезопасный, но идемпотентный метод для частичного обновления ресурса.
// PATCH /api/users/1 → Обновить только определённые поля
PATCH /api/users/1
Body: {
"name": "John Updated"
// age и email остаются без изменений
}
Response: {
"id": 1,
"name": "John Updated",
"email": "john@example.com", // Не изменился
"age": 30 // Не изменился
}
Status: 200 OK
REST контроллер
@RestController
@RequestMapping("/api/users")
public class UserController {
@PatchMapping("/{id}") // PATCH /api/users/1
public ResponseEntity<UserDTO> patchUser(
@PathVariable Long id,
@RequestBody Map<String, Object> updates) {
UserDTO patched = userService.patch(id, updates);
return ResponseEntity.ok(patched);
}
}
PUT vs PATCH
// PUT — полная замена
PUT /api/users/1
Body: {"name": "John"}
// Результат: {"id": 1, "name": "John", "email": null, "age": null}
// PATCH — частичное обновление
PATCH /api/users/1
Body: {"name": "John"}
// Результат: {"id": 1, "name": "John", "email": "john@example.com", "age": 30}
5. DELETE (Удалить ресурс)
DELETE — небезопасный, но идемпотентный метод для удаления ресурса.
// DELETE /api/users/1 → Удалить пользователя
DELETE /api/users/1
Response: (пусто или подтверждение)
Status: 204 No Content или 200 OK
// ✅ Второй вызов DELETE также возвращает 204 (идемпотентен)
DELETE /api/users/1 // Уже удалён
Status: 204 No Content // Тот же результат
REST контроллер
@RestController
@RequestMapping("/api/users")
public class UserController {
@DeleteMapping("/{id}") // DELETE /api/users/1
public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build(); // 204 No Content
}
}
6. HEAD (Получить метаданные)
HEAD — как GET, но возвращает только заголовки без тела ответа. Используется для проверки доступности ресурса.
// HEAD /api/users/1 → Проверить существование
HEAD /api/users/1
Response: (пусто)
Status: 200 OK если существует, 404 Not Found если нет
REST контроллер
@RestController
@RequestMapping("/api/users")
public class UserController {
@RequestMapping(method = RequestMethod.HEAD, value = "/{id}")
public ResponseEntity<Void> headUser(@PathVariable Long id) {
boolean exists = userService.exists(id);
return exists ? ResponseEntity.ok().build() : ResponseEntity.notFound().build();
}
}
7. OPTIONS (Получить доступные методы)
OPTIONS — получает информацию о доступных HTTP методах для ресурса.
// OPTIONS /api/users/1 → Какие методы доступны?
OPTIONS /api/users/1
Response:
Allow: GET, POST, PUT, PATCH, DELETE, HEAD, OPTIONS
Status: 200 OK
REST контроллер
@RestController
@RequestMapping("/api/users")
public class UserController {
@RequestMapping(method = RequestMethod.OPTIONS, value = "/{id}")
public ResponseEntity<Void> optionsUser(@PathVariable Long id) {
return ResponseEntity.ok()
.allow(HttpMethod.GET, HttpMethod.POST, HttpMethod.PUT,
HttpMethod.PATCH, HttpMethod.DELETE, HttpMethod.HEAD,
HttpMethod.OPTIONS)
.build();
}
}
Сравнение HTTP методов
| Метод | Безопасен | Идемпотентен | Использование | Тело запроса | Статус |
|---|---|---|---|---|---|
| GET | ✅ | ✅ | Получить данные | Нет | 200 |
| POST | ❌ | ❌ | Создать ресурс | Да | 201 |
| PUT | ❌ | ✅ | Заменить полностью | Да | 200/204 |
| PATCH | ❌ | ✅ | Обновить частично | Да | 200 |
| DELETE | ❌ | ✅ | Удалить ресурс | Нет | 204 |
| HEAD | ✅ | ✅ | Проверить | Нет | 200 |
| OPTIONS | ✅ | ✅ | Метаданные | Нет | 200 |
Лучшие практики REST
// ✅ Используй правильные методы
GET /api/users // Получить список
GET /api/users/1 // Получить одного
POST /api/users // Создать
PUT /api/users/1 // Заменить полностью
PATCH /api/users/1 // Обновить частично
DELETE /api/users/1 // Удалить
// ✅ Правильные статус коды
200 OK // Успешно (для GET, PUT, PATCH)
201 Created // Создано (для POST)
204 No Content // Успешно, но нет тела (для DELETE, PUT без тела)
400 Bad Request // Ошибка валидации
401 Unauthorized // Не аутентифицирован
403 Forbidden // Нет прав доступа
404 Not Found // Ресурс не найден
500 Internal Error // Ошибка сервера
// ✅ Версионирование
GET /api/v1/users
GET /api/v2/users
// ❌ Не используй GET для изменения
GET /api/users/1/delete // ❌ Неправильно
DELETE /api/users/1 // ✅ Правильно
// ❌ Не используй глаголы в URL
POST /api/users/create // ❌ Неправильно
POST /api/users // ✅ Правильно
Практический пример полного CRUD
@RestController
@RequestMapping("/api/users")
public class UserController {
@GetMapping
public ResponseEntity<List<UserDTO>> getAll() {
return ResponseEntity.ok(userService.findAll());
}
@GetMapping("/{id}")
public ResponseEntity<UserDTO> getById(@PathVariable Long id) {
return userService.findById(id)
.map(ResponseEntity::ok)
.orElse(ResponseEntity.notFound().build());
}
@PostMapping
public ResponseEntity<UserDTO> create(@RequestBody CreateUserRequest request) {
UserDTO created = userService.create(request);
return ResponseEntity
.created(URI.create("/api/users/" + created.getId()))
.body(created);
}
@PutMapping("/{id}")
public ResponseEntity<UserDTO> update(
@PathVariable Long id,
@RequestBody UpdateUserRequest request) {
UserDTO updated = userService.update(id, request);
return ResponseEntity.ok(updated);
}
@PatchMapping("/{id}")
public ResponseEntity<UserDTO> patch(
@PathVariable Long id,
@RequestBody Map<String, Object> updates) {
UserDTO patched = userService.patch(id, updates);
return ResponseEntity.ok(patched);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> delete(@PathVariable Long id) {
userService.delete(id);
return ResponseEntity.noContent().build();
}
}
Заключение
Основные HTTP методы REST:
- GET — получить данные (безопасный, идемпотентный)
- POST — создать ресурс (небезопасный, неидемпотентный)
- PUT — заменить полностью (небезопасный, идемпотентный)
- PATCH — обновить частично (небезопасный, идемпотентный)
- DELETE — удалить (небезопасный, идемпотентный)
- HEAD — проверить (безопасный, идемпотентный)
- OPTIONS — метаданные (безопасный, идемпотентный)
Правильное использование методов — основа чистого и предсказуемого REST API.