Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
HTTP коды ответа — группы и их значения
HTTP статус коды разделены на 5 групп (классов) по своему значению. Каждый класс начинается с определённой цифры и имеет свою смысловую нагрузку.
1. 1xx — Информационные коды (Informational)
Эти коды означают, что запрос получен и обработка продолжается.
// 100 Continue
// Клиент отправляет большой body и ждёт подтверждения
GET /api/upload HTTP/1.1
Expect: 100-continue
Content-Length: 1000000
// Сервер отвечает
HTTP/1.1 100 Continue
// Клиент отправляет body
// 101 Switching Protocols
// Переключение на другой протокол (например WebSocket)
GET /chat HTTP/1.1
Upgrade: websocket
Connection: Upgrade
HTTP/1.1 101 Switching Protocols
Коды:
100 Continue— можешь отправлять тело запроса101 Switching Protocols— переход на другой протокол (WebSocket)102 Processing— обработка продолжается (WebDAV)
⚠️ Редко встречаются в обычных приложениях.
2. 2xx — Успешные коды (Success)
Это семейство кодов означает, что запрос успешно обработан.
// В Spring REST контроллере
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
@GetMapping("/{id}")
public ResponseEntity<UserDTO> getUser(@PathVariable UUID id) {
UserDTO user = userService.getUserById(id);
// 200 OK (по умолчанию)
return ResponseEntity.ok(user);
}
@PostMapping
public ResponseEntity<UserDTO> createUser(@RequestBody CreateUserRequest request) {
UserDTO created = userService.create(request);
// 201 Created
return ResponseEntity.status(HttpStatus.CREATED)
.header("Location", "/api/v1/users/" + created.getId())
.body(created);
}
@PutMapping("/{id}")
public ResponseEntity<UserDTO> updateUser(
@PathVariable UUID id,
@RequestBody UpdateUserRequest request) {
UserDTO updated = userService.update(id, request);
// 200 OK или 204 No Content
return ResponseEntity.ok(updated);
}
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteUser(@PathVariable UUID id) {
userService.delete(id);
// 204 No Content
return ResponseEntity.noContent().build();
}
}
Основные коды:
200 OK— успешный запрос, ответ содержит данные201 Created— ресурс создан, нужен Location header202 Accepted— запрос принят для обработки (асинхронная обработка)204 No Content— успешно, но нет содержимого для возврата (обновление, удаление)206 Partial Content— частичное содержимое (streaming, range requests)
3. 3xx — Редирект коды (Redirection)
Эти коды означают, что нужно выполнить дополнительное действие для завершения запроса.
// 301 Moved Permanently
GET /old-api/users HTTP/1.1
HTTP/1.1 301 Moved Permanently
Location: /api/v1/users
// 302 Found (временный редирект)
GET /promo/summer HTTP/1.1
HTTP/1.1 302 Found
Location: /products?category=summer
// В Spring
@GetMapping("/old-endpoint")
public String oldEndpoint() {
return "redirect:/new-endpoint"; // 302 временный
}
// 304 Not Modified (кэширование)
GET /api/users HTTP/1.1
If-Modified-Since: Mon, 20 Mar 2026 10:00:00 GMT
HTTP/1.1 304 Not Modified
// Клиент использует закэшированный ответ
// В Spring
@GetMapping("/data")
public ResponseEntity<Data> getData(
@RequestHeader("If-None-Match") Optional<String> etag) {
String currentETag = "123abc";
if (etag.isPresent() && etag.get().equals(currentETag)) {
return ResponseEntity.status(HttpStatus.NOT_MODIFIED).build();
}
return ResponseEntity.ok()
.header("ETag", currentETag)
.body(data);
}
// 307 Temporary Redirect (сохраняет метод запроса)
GET /api/users HTTP/1.1
HTTP/1.1 307 Temporary Redirect
Location: /api/v2/users
// Клиент отправит GET на новый URL
// 308 Permanent Redirect (сохраняет метод запроса)
POST /api/users HTTP/1.1
HTTP/1.1 308 Permanent Redirect
Location: /api/v2/users
// Клиент отправит POST на новый URL
Основные коды:
301 Moved Permanently— постоянный редирект302 Found— временный редирект (наиболее распространён)304 Not Modified— используй кэш (для 304 не отправляется body)307 Temporary Redirect— как 302, но сохраняет метод308 Permanent Redirect— как 301, но сохраняет метод
4. 4xx — Ошибки клиента (Client Error)
Это коды, которые означают ошибку в запросе клиента.
@RestController
@RequestMapping("/api/v1/users")
public class UserController {
// 400 Bad Request
@PostMapping
public ResponseEntity<?> createUser(@RequestBody CreateUserRequest request) {
if (request.getEmail() == null || request.getEmail().isEmpty()) {
return ResponseEntity.badRequest()
.body(Map.of("error", "Email is required"));
}
// ...
}
// 401 Unauthorized
@GetMapping("/me")
public ResponseEntity<UserDTO> getCurrentUser(
@RequestHeader("Authorization") Optional<String> auth) {
if (auth.isEmpty()) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(null);
}
// ...
}
// 403 Forbidden
@DeleteMapping("/{id}")
public ResponseEntity<?> deleteUser(
@PathVariable UUID id,
@RequestHeader("Authorization") String auth) {
User currentUser = tokenService.getUserFromToken(auth);
User targetUser = userService.findById(id);
if (!currentUser.getId().equals(targetUser.getId()) && !currentUser.isAdmin()) {
return ResponseEntity.status(HttpStatus.FORBIDDEN)
.body(Map.of("error", "Access denied"));
}
// ...
}
// 404 Not Found
@GetMapping("/{id}")
public ResponseEntity<?> getUser(@PathVariable UUID id) {
Optional<User> user = userService.findById(id);
if (user.isEmpty()) {
return ResponseEntity.notFound().build();
}
return ResponseEntity.ok(user.get());
}
// 409 Conflict (данные конфликтуют)
@PostMapping
public ResponseEntity<?> createUser(@RequestBody CreateUserRequest request) {
if (userService.existsByEmail(request.getEmail())) {
return ResponseEntity.status(HttpStatus.CONFLICT)
.body(Map.of("error", "Email already exists"));
}
// ...
}
// 422 Unprocessable Entity (семантическая ошибка)
@PostMapping
public ResponseEntity<?> createUser(@RequestBody CreateUserRequest request) {
if (request.getAge() < 18) {
return ResponseEntity.status(HttpStatus.UNPROCESSABLE_ENTITY)
.body(Map.of("error", "Age must be >= 18"));
}
// ...
}
// 429 Too Many Requests (rate limiting)
@GetMapping
public ResponseEntity<?> listUsers() {
if (rateLimiter.isExceeded()) {
return ResponseEntity.status(HttpStatus.TOO_MANY_REQUESTS)
.header("Retry-After", "60")
.body(Map.of("error", "Rate limit exceeded"));
}
// ...
}
}
Основные коды:
400 Bad Request— ошибка в синтаксисе запроса401 Unauthorized— требуется аутентификация403 Forbidden— аутентифицирован, но не имеет доступа404 Not Found— ресурс не найден409 Conflict— конфликт (например дублирование уникального поля)410 Gone— ресурс удалён и больше не вернётся422 Unprocessable Entity— семантическая ошибка в данных429 Too Many Requests— слишком много запросов (rate limiting)
5. 5xx — Ошибки сервера (Server Error)
Это коды, которые означают ошибку на стороне сервера.
@RestController
@RequestMapping("/api/v1/orders")
public class OrderController {
// 500 Internal Server Error
@GetMapping("/{id}")
public ResponseEntity<?> getOrder(@PathVariable UUID id) {
try {
Order order = orderService.getOrderById(id);
return ResponseEntity.ok(order);
} catch (Exception e) {
// Логируем ошибку
logger.error("Error fetching order", e);
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(Map.of("error", "Internal server error"));
}
}
// 501 Not Implemented
@PostMapping("/{id}/cancel")
public ResponseEntity<?> cancelOrder(@PathVariable UUID id) {
// Feature не реализована
return ResponseEntity.status(HttpStatus.NOT_IMPLEMENTED)
.body(Map.of("error", "Order cancellation not implemented yet"));
}
// 502 Bad Gateway (когда обращаемся к external API)
@GetMapping("/{id}/tracking")
public ResponseEntity<?> getTrackingInfo(@PathVariable UUID id) {
try {
return ResponseEntity.ok(externalShippingAPI.getTracking(id));
} catch (TimeoutException | ConnectionException e) {
logger.error("External API error", e);
return ResponseEntity.status(HttpStatus.BAD_GATEWAY)
.body(Map.of("error", "Shipping service unavailable"));
}
}
// 503 Service Unavailable
@GetMapping("/{id}/recommend")
public ResponseEntity<?> getRecommendations(@PathVariable UUID id) {
if (!recommendationService.isHealthy()) {
return ResponseEntity.status(HttpStatus.SERVICE_UNAVAILABLE)
.header("Retry-After", "300")
.body(Map.of("error", "Service temporarily unavailable"));
}
// ...
}
// 504 Gateway Timeout
@GetMapping("/{id}/estimate")
public ResponseEntity<?> estimateDelivery(@PathVariable UUID id) {
try {
return ResponseEntity.ok(externalCalculator.estimate(id));
} catch (TimeoutException e) {
return ResponseEntity.status(HttpStatus.GATEWAY_TIMEOUT)
.body(Map.of("error", "Calculation service timeout"));
}
}
}
Основные коды:
500 Internal Server Error— общая ошибка сервера501 Not Implemented— метод/функция не реализована502 Bad Gateway— ошибка при обращении к upstream сервису503 Service Unavailable— сервер временно недоступен (maintenance, overload)504 Gateway Timeout— timeout при обращении к upstream
Таблица правильного выбора кодов
| Ситуация | Код | Пример |
|---|---|---|
| Успешный запрос с данными | 200 | GET /users/1 |
| Создан новый ресурс | 201 | POST /users |
| Успешно, нет содержимого | 204 | DELETE /users/1 |
| Ошибка в данных | 400 | Неверный JSON |
| Не аутентифицирован | 401 | Отсутствует токен |
| Недостаточно прав | 403 | Удаление чужого ресурса |
| Ресурс не существует | 404 | GET /users/invalid-id |
| Конфликт данных | 409 | Email уже существует |
| Семантическая ошибка | 422 | Age < 0 |
| Ошибка сервера | 500 | Необработанное исключение |
| Сервис недоступен | 503 | Maintenance режим |
Best Practices
- Всегда возвращай правильный статус код — это помогает клиентам
- Не путай 401 и 403 — 401 для отсутствия аутентификации, 403 для недостатка прав
- Используй Location header при 201 Created
- Не возвращай 5xx если это ошибка клиента (должен быть 4xx)
- Логируй все 5xx ошибки для анализа
- Возвращай консистентный формат ошибок
- Используй 204 вместо 200 когда нет содержимого