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

Из чего состоит структура HTTP-запроса

1.3 Junior🔥 251 комментариев
#REST API и HTTP

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Структура HTTP-запроса

HTTP-запрос — это сообщение, которое клиент (браузер, мобильное приложение) отправляет серверу для получения ресурса или выполнения действия. Структура запроса стандартизирована и состоит из четырех основных частей.

Основные части HTTP-запроса

1. Request Line (Строка запроса)

METHOD /path/to/resource?param1=value1&param2=value2 HTTP/1.1

Компоненты:

  • METHOD — HTTP метод (GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS)
  • URI — путь и параметры ресурса
  • HTTP Version — версия протокола (HTTP/1.1, HTTP/2, HTTP/3)

Примеры:

GET /api/users HTTP/1.1
POST /api/users HTTP/1.1
DELETE /api/users/123 HTTP/1.1
PUT /api/users/123 HTTP/1.1

2. Request Headers (Заголовки)

Описывают метаинформацию о запросе:

Host: example.com
User-Agent: Mozilla/5.0 (Chrome/91.0)
Accept: application/json
Content-Type: application/json
Content-Length: 1234
Authorization: Bearer token_123456
Cookie: session_id=abc123; user_pref=dark_mode

Частые заголовки:

ЗаголовокОписание
HostХост сервера, к которому идет запрос
User-AgentИнформация о клиенте (браузер, ОС)
AcceptФормат, который клиент может принять (JSON, HTML)
Content-TypeФормат отправляемых данных
Content-LengthРазмер тела запроса в байтах
AuthorizationТокен аутентификации
CookieCookies сессии и предпочтений
RefererОткуда клиент пришел
Accept-EncodingСжатие (gzip, deflate)
X-Custom-HeaderКастомные заголовки (с префиксом X-)

3. Empty Line (Пустая строка)

\r\n\r\n

Отделяет заголовки от тела запроса.

4. Request Body (Тело запроса)

Содержит данные, отправляемые серверу:

{
  "username": "alice",
  "password": "secret123",
  "email": "alice@example.com"
}

Body обязателен для:

  • POST запросов
  • PUT запросов
  • PATCH запросов

Body НЕ отправляется для:

  • GET запросов
  • DELETE запросов (обычно)
  • HEAD запросов

Полный пример HTTP-запроса

POST /api/v1/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 52
Authorization: Bearer eyJhbGc...
Accept: application/json

{
  "name": "Alice",
  "email": "alice@example.com",
  "age": 30
}

HTTP Методы

GET — получить ресурс

GET /api/users/123 HTTP/1.1
Host: api.example.com

# Нет body
# Безопасный (не меняет данные)
# Можно кешировать

POST — создать ресурс

POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json

{"name": "Alice", "email": "alice@example.com"}
# Есть body
# Может иметь side effects

PUT — полностью заменить ресурс

PUT /api/users/123 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{"name": "Alice Updated", "email": "alice_new@example.com"}
# Замена всех полей

PATCH — частично обновить ресурс

PATCH /api/users/123 HTTP/1.1
Host: api.example.com
Content-Type: application/json

{"email": "alice_new@example.com"}
# Обновление только переданных полей

DELETE — удалить ресурс

DELETE /api/users/123 HTTP/1.1
Host: api.example.com

# Нет body

HEAD — как GET, но без body

HEAD /api/users HTTP/1.1
Host: api.example.com

# Используется для проверки доступности ресурса
# Возвращает только заголовки, не body

Примеры с Python

С использованием requests

import requests

# GET запрос
response = requests.get(
    'https://api.example.com/api/users/123',
    headers={
        'Authorization': 'Bearer token_123',
        'Accept': 'application/json'
    }
)

# POST запрос с данными
response = requests.post(
    'https://api.example.com/api/users',
    headers={
        'Content-Type': 'application/json',
        'Authorization': 'Bearer token_123'
    },
    json={
        'name': 'Alice',
        'email': 'alice@example.com'
    }
)

# PATCH запрос
response = requests.patch(
    'https://api.example.com/api/users/123',
    headers={
        'Content-Type': 'application/json',
        'Authorization': 'Bearer token_123'
    },
    json={'email': 'alice_new@example.com'}
)

# DELETE запрос
response = requests.delete(
    'https://api.example.com/api/users/123',
    headers={'Authorization': 'Bearer token_123'}
)

С использованием curl

# GET
curl https://api.example.com/api/users/123 \
  -H 'Authorization: Bearer token_123'

# POST
curl -X POST https://api.example.com/api/users \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer token_123' \
  -d '{"name": "Alice", "email": "alice@example.com"}'

# PATCH
curl -X PATCH https://api.example.com/api/users/123 \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer token_123' \
  -d '{"email": "alice_new@example.com"}'

# DELETE
curl -X DELETE https://api.example.com/api/users/123 \
  -H 'Authorization: Bearer token_123'

Как выглядит сырой HTTP-запрос

# Если бы мы отправляли вручную через socket

import socket

request = b'''POST /api/users HTTP/1.1
Host: api.example.com
Content-Type: application/json
Content-Length: 52

{"name": "Alice", "email": "alice@example.com"}'''

socket_obj = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
socket_obj.connect(('api.example.com', 80))
socket_obj.sendall(request)
response = socket_obj.recv(4096)

Типичные проблемы при работе с запросами

1. Неправильный Content-Type

# ❌ Плохо: отправляем JSON, но говорим что это form
response = requests.post(
    'https://api.example.com/api/users',
    headers={'Content-Type': 'application/x-www-form-urlencoded'},
    json={'name': 'Alice'}  # Сервер не поймет
)

# ✅ Хорошо
response = requests.post(
    'https://api.example.com/api/users',
    headers={'Content-Type': 'application/json'},
    json={'name': 'Alice'}
)

2. Отсутствие Authorization

# ❌ Плохо: забыли авторизацию
response = requests.get('https://api.example.com/api/users')
# 401 Unauthorized

# ✅ Хорошо
response = requests.get(
    'https://api.example.com/api/users',
    headers={'Authorization': 'Bearer token_123'}
)

3. Query параметры vs Body

# GET с параметрами в URL
response = requests.get(
    'https://api.example.com/api/users',
    params={'status': 'active', 'page': 1}
)
# URL: /api/users?status=active&page=1

# POST с данными в body
response = requests.post(
    'https://api.example.com/api/users',
    json={'name': 'Alice'}  # В body
)

4. Content-Length

# Обычно requests считает Content-Length автоматически
response = requests.post(
    'https://api.example.com/api/users',
    json={'name': 'Alice'}
)
# requests добавит Content-Length автоматически

# Но если отправляем вручную:
data = b'{"name": "Alice"}'
headers = {'Content-Length': len(data)}  # Важно!

FastAPI и HTTP-запросы

from fastapi import FastAPI, Header, Body
from pydantic import BaseModel

app = FastAPI()

class User(BaseModel):
    name: str
    email: str

@app.get('/api/users/{user_id}')
def get_user(
    user_id: int,
    authorization: str = Header(...)  # Из заголовков
):
    return {'id': user_id}

@app.post('/api/users')
def create_user(
    user: User,  # Из body (JSON)
    authorization: str = Header(...)  # Из заголовков
):
    return {'id': 1, 'name': user.name, 'email': user.email}

@app.patch('/api/users/{user_id}')
def update_user(
    user_id: int,
    user: User  # Из body
):
    return {'id': user_id}

@app.delete('/api/users/{user_id}')
def delete_user(user_id: int):
    return {'status': 'deleted'}

Итоговое резюме

HTTP-запрос состоит из:

  1. Request Line — метод, путь, версия
  2. Headers — метаинформация
  3. Empty Line — разделитель
  4. Body — данные (опционально)

Помни:

  • GET обычно без body
  • POST/PUT/PATCH — с body
  • Всегда указывай правильный Content-Type
  • Authorization идет в заголовках
  • Content-Length обычно вычисляется автоматически
Из чего состоит структура HTTP-запроса | PrepBro