Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
HTTP статус-коды: справочник разработчика
Статус-коды — это трехзначные числа, которые сервер отправляет в ответ на HTTP запрос. Они указывают на результат обработки запроса.
Структура статус-кодов
Первая цифра указывает на класс ответа:
- 1xx (100-199) — информационные ответы (редко используются)
- 2xx (200-299) — успешные ответы
- 3xx (300-399) — перенаправления
- 4xx (400-499) — ошибки клиента
- 5xx (500-599) — ошибки сервера
2xx — Успешные ответы
Эти коды означают, что запрос успешно обработан.
200 OK
Запрос выполнен успешно. Ответ содержит запрошенные данные.
from flask import Flask, jsonify
app = Flask(__name__)
@app.route('/users/<id>')
def get_user(id):
user = {'id': id, 'name': 'John Doe'}
return jsonify(user), 200 # ✅ 200 OK
201 Created
Ресурс успешно создан (обычно после POST).
@app.route('/users', methods=['POST'])
def create_user():
user = {'id': 123, 'name': 'John'}
return jsonify(user), 201 # ✅ Ресурс создан
204 No Content
Запрос успешен, но нет содержимого в ответе (часто после DELETE).
@app.route('/users/<id>', methods=['DELETE'])
def delete_user(id):
# Удаляем пользователя
return '', 204 # ✅ Удалено успешно, нет ответа
202 Accepted
Запрос принят, но обработка еще в процессе (асинхронные операции).
@app.route('/reports', methods=['POST'])
def generate_report():
# Очень долгая операция
# Запускаем в фоне (celery, queue, etc)
task_id = start_long_task()
return {'task_id': task_id, 'status': 'processing'}, 202
3xx — Перенаправления
Клиент должен предпринять дополнительные действия.
301 Moved Permanently
Ресурс перемещен на новый URL навсегда. Браузер обновит закладки.
@app.route('/old-page')
def old_page():
return redirect('/new-page', code=301)
# Старые ссылки переучат на новый URL
302 Found
Временное перенаправление на другой URL.
@app.route('/login')
def login():
if already_authenticated():
return redirect('/dashboard', code=302)
304 Not Modified
Ресурс не изменился с момента последнего запроса. Используется для кеширования.
@app.route('/data')
def get_data():
last_modified = '2024-01-15'
if_modified_since = request.headers.get('If-Modified-Since')
if if_modified_since == last_modified:
return '', 304 # Клиент может использовать кеш
return jsonify({'data': 'new data'}), 200
307 Temporary Redirect
Временное перенаправление (как 302, но браузер сохранит метод запроса).
@app.route('/api/old')
def api_old():
return redirect('/api/new', code=307)
# POST на /api/old будет POST на /api/new (не GET)
4xx — Ошибки клиента
Проблема в запросе клиента.
400 Bad Request
Запрос неправильно сформирован (неверный JSON, неверные параметры).
@app.route('/users', methods=['POST'])
def create_user():
try:
data = request.get_json()
if not data.get('email'):
return {'error': 'Email required'}, 400 # ❌ Неверные данные
return jsonify(data), 201
except:
return {'error': 'Invalid JSON'}, 400
401 Unauthorized
Требуется аутентификация (нет токена или неверный токен).
from functools import wraps
from flask import request
def require_auth(f):
@wraps(f)
def decorated(*args, **kwargs):
token = request.headers.get('Authorization')
if not token or not verify_token(token):
return {'error': 'Unauthorized'}, 401 # ❌ Нужно авторизоваться
return f(*args, **kwargs)
return decorated
@app.route('/profile')
@require_auth
def get_profile():
return {'profile': 'data'}
403 Forbidden
Авторизован, но нет прав на доступ к ресурсу.
@app.route('/admin')
def admin_panel():
user = get_current_user()
if user.role != 'admin':
return {'error': 'Access denied'}, 403 # ❌ Нет прав
return {'admin': 'data'}
404 Not Found
Ресурс не найден.
@app.route('/users/<id>')
def get_user(id):
user = db.query(User).get(id)
if not user:
return {'error': 'User not found'}, 404 # ❌ Ресурса нет
return jsonify(user)
409 Conflict
Запрос конфликтует с текущим состоянием (например, дублирование).
@app.route('/users', methods=['POST'])
def create_user():
email = request.json['email']
if db.query(User).filter_by(email=email).first():
return {'error': 'Email already exists'}, 409 # ❌ Дублирование
user = User(email=email)
db.add(user)
db.commit()
return jsonify(user), 201
429 Too Many Requests
Слишком много запросов (rate limiting).
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
limiter = Limiter(app, key_func=get_remote_address)
@app.route('/api/data')
@limiter.limit('10 per minute') # Максимум 10 запросов в минуту
def get_data():
return {'data': 'value'}
# Если больше 10 запросов → 429 Too Many Requests
5xx — Ошибки сервера
Проблема в обработке запроса на сервере.
500 Internal Server Error
Ошибка в коде сервера (необработанное исключение).
@app.route('/calculate')
def calculate():
try:
result = 10 / 0 # ZeroDivisionError!
except Exception as e:
# В логах: ERROR: division by zero
return {'error': 'Internal server error'}, 500 # ❌ Ошибка сервера
501 Not Implemented
Метод не реализован на сервере.
@app.route('/resource', methods=['PATCH'])
def patch_resource():
return {'error': 'PATCH not implemented'}, 501
502 Bad Gateway
Ошибка между серверами (прокси → backend).
Когда Nginx не может подключиться к Flask приложению:
GET /api → Nginx (502 Bad Gateway)
↓ (не может подключиться)
Flask (недоступен)
503 Service Unavailable
Сервис недоступен (обслуживание, перегрузка).
@app.route('/api')
def api():
if not db.is_connected():
return {'error': 'Database is down'}, 503 # ❌ Сервис недоступен
return {'data': 'value'}
504 Gateway Timeout
Тайм-аут при ожидании ответа от другого сервера.
Когда backend слишком долго отвечает:
GET /api → Nginx (ждет 30 сек)
↓ (timeout)
Flask (долгая обработка)
Ответ: 504 Gateway Timeout
Таблица статус-кодов
| Код | Название | Используется для | Пример |
|---|---|---|---|
| 200 | OK | Успешный GET/PUT | return user, 200 |
| 201 | Created | Успешный POST | return created_user, 201 |
| 204 | No Content | Успешный DELETE | return '', 204 |
| 301 | Moved Permanently | Переезд сайта | redirect('/new', 301) |
| 304 | Not Modified | Кеш валиден | Если данные не изменились |
| 400 | Bad Request | Ошибка в JSON | Неверный формат данных |
| 401 | Unauthorized | Нет токена | Требуется login |
| 403 | Forbidden | Нет прав | Недостаточно прав доступа |
| 404 | Not Found | Ресурс не существует | GET /users/999 (не существует) |
| 409 | Conflict | Конфликт/дублирование | Email уже зарегистрирован |
| 429 | Too Many Requests | Rate limiting | Слишком много запросов |
| 500 | Internal Server Error | Баг в коде | Exception не обработано |
| 502 | Bad Gateway | Прокси не может подключиться | Nginx → Flask (отключен) |
| 503 | Service Unavailable | Обслуживание/перегрузка | БД выключена |
Лучшие практики при использовании статус-кодов
# ✅ Правильно: используем нужные коды
@app.route('/users', methods=['POST'])
def create_user():
try:
data = request.get_json()
# Валидация
if not data.get('email'):
return {'error': 'Email required'}, 400 # ✓ 400 Bad Request
# Проверка существования
if User.query.filter_by(email=data['email']).first():
return {'error': 'Email exists'}, 409 # ✓ 409 Conflict
# Создание
user = User(email=data['email'])
db.add(user)
db.commit()
return jsonify(user), 201 # ✓ 201 Created
except Exception as e:
return {'error': 'Server error'}, 500 # ✓ 500 Internal Error
# ❌ Неправильно: всегда 200
@app.route('/users', methods=['POST'])
def create_user():
data = request.get_json()
if not data.get('email'):
return {'ok': False, 'error': 'Email required'}, 200 # ✗ Неправильно!
# Статус-код не отражает результат
Вывод
Используй правильные статус-коды:
- 2xx — успех
- 3xx — перенаправления
- 4xx — ошибка клиента (исправить запрос)
- 5xx — ошибка сервера (исправить код)
Правильные статус-коды улучшают:
- Читаемость и понятность API
- Обработку ошибок на клиенте
- SEO и кеширование
- Мониторинг приложения