HTTP коды ответа — это трёхзначные числа, которые сервер отправляет клиенту для указания результата обработки запроса:
// Примеры популярных кодов
200 // OK — всё хорошо
404 // Not Found — страница не найдена
500 // Internal Server Error — ошибка сервера
401 // Unauthorized — требуется авторизацияHTTP коды ответа — это как светофор в мире веб-разработки. Они говорят нам, что происходит с нашим запросом! 🚦
HTTP коды состоят из трёх цифр, где первая цифра определяет класс ответа:
// Структура HTTP кода
[Класс][Подкласс][Конкретный код]
1-5 0-9 0-9
// Примеры
200 // Класс 2 (успех), код 00 (OK)
404 // Класс 4 (ошибка клиента), код 04 (Not Found)Эти коды говорят: “Я получил ваш запрос, работаю над ним!” 🔄
// Основные информационные коды
100 // Continue — продолжайте отправку
101 // Switching Protocols — переключение протоколов
102 // Processing — запрос обрабатывается
103 // Early Hints — ранние подсказки
// Пример использования
fetch('/api/upload', {
method: 'POST',
body: largeFile
}).then(response => {
// Может получить 100 Continue перед основным ответом
console.log(response.status); // 200 после завершения
});Самые приятные коды — всё прошло отлично! 🎉
// Популярные коды успеха
200 // OK — стандартный успех
201 // Created — ресурс создан
202 // Accepted — запрос принят к обработке
204 // No Content — успех, но нет содержимого
206 // Partial Content — частичное содержимое
// Примеры использования
// GET запрос
fetch('/api/users')
.then(response => {
console.log(response.status); // 200 OK
return response.json();
});
// POST запрос (создание)
fetch('/api/users', {
method: 'POST',
body: JSON.stringify(userData)
}).then(response => {
console.log(response.status); // 201 Created
});
// DELETE запрос
fetch('/api/users/123', {
method: 'DELETE'
}).then(response => {
console.log(response.status); // 204 No Content
});Коды говорят: “То, что вы ищете, находится в другом месте!” 🗺️
// Коды перенаправления
300 // Multiple Choices — несколько вариантов
301 // Moved Permanently — постоянное перенаправление
302 // Found — временное перенаправление
304 // Not Modified — не изменялось
307 // Temporary Redirect — временное перенаправление
308 // Permanent Redirect — постоянное перенаправление
// Обработка перенаправлений
fetch('/old-page', {
redirect: 'follow' // автоматически следовать перенаправлениям
}).then(response => {
if (response.redirected) {
console.log('Перенаправлен на:', response.url);
}
});
// Кэширование с 304
fetch('/api/data', {
headers: {
'If-None-Match': etag // проверка кэша
}
}).then(response => {
if (response.status === 304) {
console.log('Данные не изменились, используем кэш');
}
});“Вы что-то сделали не так!” — говорят эти коды 🤦♂️
// Популярные ошибки клиента
400 // Bad Request — неправильный запрос
401 // Unauthorized — требуется авторизация
403 // Forbidden — доступ запрещён
404 // Not Found — не найдено
405 // Method Not Allowed — метод не разрешён
409 // Conflict — конфликт данных
422 // Unprocessable Entity — невалидные данные
429 // Too Many Requests — слишком много запросов
// Обработка ошибок клиента
async function handleRequest() {
try {
const response = await fetch('/api/protected', {
headers: {
'Authorization': `Bearer ${token}`
}
});
switch (response.status) {
case 400:
throw new Error('Неправильный запрос');
case 401:
// Перенаправляем на страницу входа
window.location.href = '/login';
break;
case 403:
throw new Error('Доступ запрещён');
case 404:
throw new Error('Ресурс не найден');
case 422:
const errors = await response.json();
console.log('Ошибки валидации:', errors);
break;
case 429:
throw new Error('Слишком много запросов, попробуйте позже');
}
} catch (error) {
console.error('Ошибка:', error.message);
}
}“Это не ваша вина, у нас проблемы!” 🔥
// Ошибки сервера
500 // Internal Server Error — внутренняя ошибка
501 // Not Implemented — не реализовано
502 // Bad Gateway — плохой шлюз
503 // Service Unavailable — сервис недоступен
504 // Gateway Timeout — таймаут шлюза
505 // HTTP Version Not Supported — версия HTTP не поддерживается
// Обработка серверных ошибок
async function fetchWithRetry(url, options = {}, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
const response = await fetch(url, options);
if (response.status >= 500) {
throw new Error(`Серверная ошибка: ${response.status}`);
}
return response;
} catch (error) {
if (i === maxRetries - 1) throw error;
// Экспоненциальная задержка
await new Promise(resolve =>
setTimeout(resolve, Math.pow(2, i) * 1000)
);
}
}
}| Код | Название | Значение | Когда использовать |
|---|---|---|---|
| 200 | OK | Успешный запрос | GET, PUT запросы |
| 201 | Created | Ресурс создан | POST запросы |
| 204 | No Content | Успех без содержимого | DELETE запросы |
| 301 | Moved Permanently | Постоянное перенаправление | Изменение URL |
| 304 | Not Modified | Не изменялось | Кэширование |
| 400 | Bad Request | Неправильный запрос | Ошибки валидации |
| 401 | Unauthorized | Не авторизован | Нужен логин |
| 403 | Forbidden | Доступ запрещён | Нет прав |
| 404 | Not Found | Не найдено | Несуществующий ресурс |
| 500 | Internal Server Error | Ошибка сервера | Проблемы на сервере |
class ApiClient {
async request(url, options = {}) {
try {
const response = await fetch(url, {
headers: {
'Content-Type': 'application/json',
...options.headers
},
...options
});
// Обработка по классам кодов
if (response.status >= 200 && response.status < 300) {
return this.handleSuccess(response);
} else if (response.status >= 300 && response.status < 400) {
return this.handleRedirect(response);
} else if (response.status >= 400 && response.status < 500) {
throw await this.handleClientError(response);
} else if (response.status >= 500) {
throw await this.handleServerError(response);
}
} catch (error) {
console.error('Ошибка запроса:', error);
throw error;
}
}
async handleSuccess(response) {
if (response.status === 204) {
return null; // No Content
}
return response.json();
}
handleRedirect(response) {
// Браузер автоматически обрабатывает перенаправления
return response;
}
async handleClientError(response) {
const error = await response.json();
switch (response.status) {
case 400:
return new Error(`Неправильный запрос: ${error.message}`);
case 401:
this.redirectToLogin();
return new Error('Требуется авторизация');
case 403:
return new Error('Доступ запрещён');
case 404:
return new Error('Ресурс не найден');
case 422:
return new Error(`Ошибки валидации: ${JSON.stringify(error.errors)}`);
default:
return new Error(`Ошибка клиента: ${response.status}`);
}
}
async handleServerError(response) {
return new Error(`Ошибка сервера: ${response.status}`);
}
redirectToLogin() {
window.location.href = '/login';
}
}
// Использование
const api = new ApiClient();
// GET запрос
const users = await api.request('/api/users');
// POST запрос
const newUser = await api.request('/api/users', {
method: 'POST',
body: JSON.stringify({ name: 'John', email: 'john@example.com' })
});import { useState, useCallback } from 'react';
function useApi() {
const [loading, setLoading] = useState(false);
const [error, setError] = useState(null);
const request = useCallback(async (url, options = {}) => {
setLoading(true);
setError(null);
try {
const response = await fetch(url, options);
if (!response.ok) {
const errorMessage = await getErrorMessage(response);
throw new Error(errorMessage);
}
const data = response.status === 204 ? null : await response.json();
return data;
} catch (err) {
setError(err.message);
throw err;
} finally {
setLoading(false);
}
}, []);
return { request, loading, error };
}
async function getErrorMessage(response) {
const statusMessages = {
400: 'Неправильный запрос',
401: 'Требуется авторизация',
403: 'Доступ запрещён',
404: 'Ресурс не найден',
422: 'Ошибка валидации данных',
429: 'Слишком много запросов',
500: 'Внутренняя ошибка сервера',
502: 'Плохой шлюз',
503: 'Сервис недоступен',
504: 'Таймаут шлюза'
};
try {
const errorData = await response.json();
return errorData.message || statusMessages[response.status] || `Ошибка ${response.status}`;
} catch {
return statusMessages[response.status] || `Ошибка ${response.status}`;
}
}
// Использование в компоненте
function UserList() {
const { request, loading, error } = useApi();
const [users, setUsers] = useState([]);
useEffect(() => {
const fetchUsers = async () => {
try {
const data = await request('/api/users');
setUsers(data);
} catch (err) {
console.error('Не удалось загрузить пользователей:', err.message);
}
};
fetchUsers();
}, [request]);
if (loading) return <div>Загрузка...</div>;
if (error) return <div>Ошибка: {error}</div>;
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}// ✅ Хорошо: детальная обработка
async function createUser(userData) {
try {
const response = await fetch('/api/users', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(userData)
});
if (response.status === 201) {
return await response.json();
} else if (response.status === 400) {
const errors = await response.json();
throw new ValidationError(errors);
} else if (response.status === 409) {
throw new ConflictError('Пользователь уже существует');
} else {
throw new Error(`Неожиданная ошибка: ${response.status}`);
}
} catch (error) {
console.error('Ошибка создания пользователя:', error);
throw error;
}
}
// ❌ Плохо: игнорирование кодов
async function createUserBad(userData) {
const response = await fetch('/api/users', {
method: 'POST',
body: JSON.stringify(userData)
});
return response.json(); // Может быть ошибка!
}// Express.js примеры
app.post('/api/users', async (req, res) => {
try {
// Валидация
if (!req.body.email) {
return res.status(400).json({
error: 'Email обязателен'
});
}
// Проверка существования
const existingUser = await User.findByEmail(req.body.email);
if (existingUser) {
return res.status(409).json({
error: 'Пользователь уже существует'
});
}
// Создание
const user = await User.create(req.body);
res.status(201).json(user); // Created
} catch (error) {
console.error(error);
res.status(500).json({
error: 'Внутренняя ошибка сервера'
});
}
});
app.delete('/api/users/:id', async (req, res) => {
try {
const user = await User.findById(req.params.id);
if (!user) {
return res.status(404).json({
error: 'Пользователь не найден'
});
}
await user.delete();
res.status(204).send(); // No Content
} catch (error) {
res.status(500).json({
error: 'Ошибка удаления'
});
}
});// ❌ Плохо: неправильные коды
app.post('/api/users', (req, res) => {
if (!req.body.name) {
return res.status(500).json({ error: 'Имя обязательно' }); // Должно быть 400!
}
res.status(200).json({ message: 'Создано' }); // Должно быть 201!
});
// ✅ Хорошо: правильные коды
app.post('/api/users', (req, res) => {
if (!req.body.name) {
return res.status(400).json({ error: 'Имя обязательно' });
}
const user = createUser(req.body);
res.status(201).json(user);
});// ❌ Плохо: не проверяем статус
fetch('/api/data')
.then(response => response.json()) // Может быть ошибка!
.then(data => console.log(data));
// ✅ Хорошо: проверяем статус
fetch('/api/data')
.then(response => {
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
})
.then(data => console.log(data))
.catch(error => console.error('Ошибка:', error));Понимание HTTP кодов поможет вам создавать надёжные и предсказуемые API! 🚀
Хотите больше статей для подготовки к собеседованиям? Подписывайтесь на EasyAdvice, добавляйте сайт в закладки и совершенствуйтесь каждый день 💪