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

Какие знаешь группы кодов ответа?

2.2 Middle🔥 141 комментариев
#Основы Java

Комментарии (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 header
  • 202 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

Таблица правильного выбора кодов

СитуацияКодПример
Успешный запрос с данными200GET /users/1
Создан новый ресурс201POST /users
Успешно, нет содержимого204DELETE /users/1
Ошибка в данных400Неверный JSON
Не аутентифицирован401Отсутствует токен
Недостаточно прав403Удаление чужого ресурса
Ресурс не существует404GET /users/invalid-id
Конфликт данных409Email уже существует
Семантическая ошибка422Age < 0
Ошибка сервера500Необработанное исключение
Сервис недоступен503Maintenance режим

Best Practices

  1. Всегда возвращай правильный статус код — это помогает клиентам
  2. Не путай 401 и 403 — 401 для отсутствия аутентификации, 403 для недостатка прав
  3. Используй Location header при 201 Created
  4. Не возвращай 5xx если это ошибка клиента (должен быть 4xx)
  5. Логируй все 5xx ошибки для анализа
  6. Возвращай консистентный формат ошибок
  7. Используй 204 вместо 200 когда нет содержимого
Какие знаешь группы кодов ответа? | PrepBro