HTTP и REST на пальцах
HTTP — язык общения браузера и сервера. REST — соглашение «как именно строить URL и какие методы использовать». Это фундамент любого API. Понимаешь это — понимаешь любой бэкенд.
Запрос и ответ
Браузер шлёт запрос: метод (GET, POST...), URL, заголовки, опционально тело. Сервер отвечает: status code, заголовки, тело. Вот и весь HTTP. Заголовки — мета-информация (Content-Type, Authorization, Cookie). Тело — основные данные (JSON чаще всего). Открой DevTools → Network → ты видишь каждый такой запрос своего сайта.
Методы
GET — «дай данные» (получить пользователя). POST — «прими и обработай» (создать заказ). PUT — «замени целиком». PATCH — «частичное обновление». DELETE — «удали». GET идемпотентен и без тела (параметры в URL). POST/PUT/PATCH несут JSON в теле. Это конвенция REST — большинство API ей следуют. ИИ генерирует код по этой конвенции.
Status codes
200 — OK. 201 — Created (после POST). 204 — No Content (после DELETE). 400 — Bad Request (клиент послал фигню). 401 — Unauthorized (нет авторизации). 403 — Forbidden (есть авторизация, но прав не хватает). 404 — Not Found. 409 — Conflict (например уже существует). 429 — Too Many Requests. 500 — Internal Server Error. 502 — Bad Gateway. Запомни хотя бы 200, 400, 401, 404, 500 — этого хватит на 80% случаев.
REST URL — конвенция
GET /users — список пользователей. GET /users/42 — один. POST /users — создать. PUT /users/42 — заменить. DELETE /users/42 — удалить. Глаголов в URL быть НЕ должно: GET /getUser — антипаттерн, метод GET сам говорит «получить». Вложенность для отношений: GET /users/42/orders — заказы юзера 42.
CORS — частая ловушка
Браузер не пускает JS-код одного сайта дёргать API другого без явного разрешения. Это защита от XSS. Если твой фронтенд (example.com) шлёт fetch на api.other.com — нужно чтобы api.other.com отдал заголовок Access-Control-Allow-Origin. С СВОИМ бэкендом (на том же домене или /api роуте) проблем нет. С чужим — либо просишь поддержку, либо проксируешь через свой сервер.
// === КЛИЕНТ ===
const API = 'https://example.com/api';
// GET — получить список
const r1 = await fetch(`${API}/users`);
const users = await r1.json(); // [{id:1, name:"Alex"}, ...]
// GET — один
const r2 = await fetch(`${API}/users/42`);
if (r2.status === 404) console.log('Не нашли');
const user = await r2.json();
// POST — создать (тело — JSON)
const r3 = await fetch(`${API}/users`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Иван', email: 'i@e.com' }),
});
if (r3.status === 201) {
const created = await r3.json(); // {id:43, ...}
}
// PUT — заменить целиком
await fetch(`${API}/users/42`, {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ name: 'Алексей', email: 'a@e.com' }),
});
// PATCH — обновить частично
await fetch(`${API}/users/42`, {
method: 'PATCH',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'new@e.com' }),
});
// DELETE — удалить
const r4 = await fetch(`${API}/users/42`, { method: 'DELETE' });
if (r4.status === 204) console.log('Удалён');
// === СЕРВЕР (Next.js App Router) ===
// app/api/users/route.ts
import { NextResponse } from 'next/server';
export async function GET() {
const users = await db.user.findMany();
return NextResponse.json(users);
}
export async function POST(req: Request) {
const body = await req.json();
if (!body.name || !body.email) {
return NextResponse.json(
{ error: 'name и email обязательны' },
{ status: 400 }
);
}
const created = await db.user.create({ data: body });
return NextResponse.json(created, { status: 201 });
}
// app/api/users/[id]/route.ts
export async function GET(req: Request, { params }: { params: { id: string } }) {
const user = await db.user.findUnique({ where: { id: params.id } });
if (!user) {
return NextResponse.json({ error: 'Не найден' }, { status: 404 });
}
return NextResponse.json(user);
}
export async function DELETE(req: Request, { params }: { params: { id: string } }) {
await db.user.delete({ where: { id: params.id } });
return new Response(null, { status: 204 }); // No Content
}Полный CRUD клиент-сервер на REST