Ключевой процесс в веб-разработке — это обмен данными через сеть. Практически любое взаимодействие в IT-системах — от просмотра страницы до развертывания приложения — строится на одном и том же: клиент запрашивает данные → сервер отвечает → клиент обрабатывает и отображает данные.
В серии статей мы пошагово разберём этот процесс, чтобы вы не просто видели результат, а понимали, что происходит на каждом этапе. Понимание этих процессов важно для технического писателя, который работает с продуктами для разработчиков, облачными сервисами или платформенными решениями.
Я буду ссылаться на теоретические материалы из журнала Код, принадлежащего Яндекс Практикуму. В статьях из этого цикла делается упор на практику, а ссылки на внешние материалы помогут получить необходимый контекст. Вы можете ознакомиться с соответствующей теорией на любом ресурсе по вашему выбору, «Код» выбран исключительно из соображений удобства.
В серии будет три статьи, в которых разберем следующее:
- Увидим, как устроено клиент-серверное взаимодействие;
- Понаблюдаем за тем, как браузер получает и отображает данные, а также изучим структуру веб-страниц;
- Развернем собственный локальный сервер, чтобы почувствовать, как работает веб изнутри.
В первой статье мы познакомимся с основой основ — запросом к HTTP API и ответом сервера. HTTP до сих пор остается самым популярным протоколом для клиент-серверного взаимодействия, и понимание его работы поможет разобраться по аналогии с любым другим протоколом.
Использовать будем curl — простую, но мощную утилиту, доступную в любом терминале. Важно понимать: curl
— это лишь один из способов. То же самое можно сделать через Postman или любой другой HTTP-клиент. Механика взаимодействия остаётся одной и той же, независимо от инструмента.
Теория: знакомство с HTTP API
Перед тем как вы приступите к теории, запомните: какие-то части могут показаться слишком сложными и их, скорее всего, можно пропустить, чтобы вернуться к ним в будущем. Не стесняйтесь переходить к практике, если не теория не дается.
API (Application Programming Interface) — это контракт, определяющий, как одно приложение может взаимодействовать с другим. В контракте зафиксированы основные параметры: доступные методы, форматы запросов и ответов, аутентификация.
HTTP API — это интерфейс, использующий протокол HTTP/HTTPS для передачи данных.
Данные передаются в формате JSON или XML. В данном цикле статей будет рассмотрен JSON.
Чаще всего HTTP API соответствует стилю REST, где ресурсы доступны по URL, а действия над ними выполняются через HTTP-методы.
Запрос и ответ сервера можно визуализировать следующим образом:
sequenceDiagram participant Клиент participant Сервер Клиент->>Сервер: 1. Отправка HTTP-запроса Note right of Клиент: Метод (GET/POST и т.д.)
URL, Заголовки, Тело Сервер->>Сервер: 2. Обработка запроса Note right of Сервер: Проверка аутентификации,
подготовка данных для отправки Сервер->>Клиент: 3. Отправка HTTP-ответа Note left of Сервер: Код статуса (200, 404 и т.д.)
Заголовки, Тело ответа Клиент->>Клиент: 4. Обработка ответа и отображение данных
Подробнее:
REST
REST (Representational State Transfer) — это архитектурный стиль, описывающий набор принципов построения API. В большинстве случаев HTTP API создается как RESTful API, но эти понятия не синонимичны.
Принципы REST достаточно просты и их немного, я выделю наиболее важные я первого знакомства:
- Клиент и сервер независимы, общаются через API
- Отсутствие состояния: Каждый запрос содержит всю необходимую информацию. Сервер не хранит состояние сессии.
- Единообразие: API организован по ресурсам, с API работают с помощью стандартных HTTP-методов.
Клиент — это любая система или приложение, которое отправляет HTTP-запросы к серверу и использует его API. Это может быть браузер, сервер, мобильное приложение или любой другой инструмент, как управляемый напрямую человеком, так и нет.
Ресурсы — это любые сущности, например пользователи, посты или комментарии. К ним обращаются по соответствующим URL, например api.example.com/users/1
.
Подробнее:
Структура запроса
Ниже показана структура HTTP-запроса. Именно так он выглядит для самого протокола, но не все поля этого запроса нужны всегда, а в разных клиентах некоторые поля можно не заполнять. Например, в curl
запрос без указанного метода будет считаться GET-запросом.
Метод и путь. Пример:
GET /api/v1/users
Заголовки (Headers)
- Host: адрес хоста и, опционально, номер порта;
- Content-Type: тип данных в теле запроса (
application/json
); - Authorization: токен доступа;
- Accept: какие форматы ответа ожидает клиент;
- Тело (Body) — только для методов, предполагающих отправку данных (POST, PUT, PATCH). Пример:
{ "name": "Иван", "email": "ivan@example.com" }
Методы
Следующие методы по умолчанию используются для действий с ресурсами в HTTP API:
GET: Получение ресурса. Не должен менять состояние ресурса;
POST: Создание нового ресурса;
PUT: Полное обновление ресурса;
PATCH: Частичное обновление;
DELETE Удаление ресурса.
Практика: получаем и передаем данные
Настройка окружения
Эта статья предполагает работу в терминале с поддержкой оболочки Bash.
На Windows я рекомендую использовать Git Bash, который устанавливается вместе с Git for Windows. Если у вас есть другой предпочитаемый терминал, который поддерживает Bash, можно использовать его. Работа в PowerShell технически возможно, но это не рекомендуемый вариант.
На других операционных системах можно пользоваться любым встроенным терминалом, так как в UNIX-подобных системах Bash поддержан по умолчанию.
Выбор API
В качестве провайдера API будет использован сервис JSONPlaceholder. Это сервис, который предоставляет эмулятор API (mock API). В GET-запросах он отдает настоящие данные, а при POST-запросах он эмулирует ответ, аналогичный реальному ответу сервера. Из этого следует, что в этом API нельзя на самом деле модицифировать или удалять ресурсы, так что рассмотрены будут только GET- и POST-запросы.
Аутентификация в этом API не предусмотрена.
К сожалению, документация сервиса не доступна на территории России, но я верю, что при желании вы сможете решить эту проблему. Это будет полезно само по себе, но в сценариях ниже я привожу всю необходимую информацию для работы с этим API.
JSONPlaceholder имеет 6 ресурсов:
Ресурс | Путь | Количество |
---|---|---|
Посты | /posts | 100 |
Комментарии | /comments | 500 |
Альбомы | /albums | 100 |
Фото | /photos | 5000 |
Задачи | /todos | 200 |
Пользователи | /users | 10 |
Ссылка на первый пост выглядит так: https://jsonplaceholder.typicode.com/posts/1
. Ссылка на комментарий с номером 500 выглядит так: https://jsonplaceholder.typicode.com/comments/500
.
GET-запросы
Рассмотрим разные сценарии получения и обработки данных.
Получение состояния ресурса
В первом запросе проверяем состояние самого сервера. Это будет GET-запрос, хотя явно в curl
это не указывается. Также не указывается большинство других частей запроса, которые разбирались в соответствующей секции.
Для проверки статуса используется флаг -I
, который запрашивает только заголовки HTTP-ответа и не скачивает тело запроса:
curl -I https://jsonplaceholder.typicode.com
Начало ответа должно выглядеть следующим образом:
HTTP/2 200
date: Wed, 27 Aug 2025 22:08:27 GMT
content-type: text/html; charset=UTF-8
...
Код 200
в первой строке говорит о том, что запрос выполнен успешно.
Далее попробуем получить состояние заведомо недоступного ресурса:
curl -I "https://jsonplaceholder.typicode.com/posts/9999"
Сервер принял запрос, но вернул другой ответ:
HTTP/2 404
date: Wed, 27 Aug 2025 22:31:44 GMT
content-type: application/json; charset=utf-8
...
Код 404
говорит об отсутствии запрашиваемого ресурса на сервере.
Подробнее:
Получение данных
Отправляем GET-запрос к JSONPlaceholder для получения содержимого поста с id=1
:
curl "https://jsonplaceholder.typicode.com/posts/1"
Ожидаемые ответ с соедржимым поста, не несущим особой смысловой нагрузки:
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident...",
"body": "quia et suscipit..."
}
Стоит также отправить запросы к другим ресурсам. Можно выбрать любые ресурсы в том диапазоне, который был указан в таблице выше.
Например:
curl "https://jsonplaceholder.typicode.com/users/10"
Информации о пользователях намного больше:
{
"id": 10,
"name": "Clementina DuBuque",
"username": "Moriah.Stanton",
"email": "Rey.Padberg@karina.biz",
"address": {
"street": "Kattie Turnpike",
"suite": "Suite 198",
"city": "Lebsackbury",
"zipcode": "31428-2261",
"geo": {
"lat": "-38.2386",
"lng": "57.2232"
}
},
"phone": "024-648-3804",
"website": "ambrose.net",
"company": {
"name": "Hoeger LLC",
"catchPhrase": "Centralized empowering task-force",
"bs": "target end-to-end models"
}
}
Рекомендую запросить аналогичным образом ресурсы всех типов.
Работа с вложенными ресурсами
JSONPlaceholder поддерживает иерархические маршруты, отражающие связи между ресурсами.
- У постов есть комментарии, доступные по следущему пути:
/posts/<номер>/comments
. - В альбомах есть фотографии:
/albums/<номер>/photos
. - У пользователей есть альбомы, задачи и посты:
/users/<номер>/albums
;/users/<номер>/todos
;/users/<номер>/posts
.
Попробуем запросить не просто отдельный ресурс, а все комментарии к посту 42:
curl "https://jsonplaceholder.typicode.com/posts/42/comments"
Ответ будет выглядеть как массив с объектами, начинающийся так:
[
{
"postId": 42,
"id": 206,
"name": "deserunt eveniet quam vitae velit",
"email": "Sophie@antoinette.ca",
"body": "nam iusto minus expedita numquam\net id quis\nvoluptatibus minima porro facilis dolores beatae aut sit\naut quia suscipit"
},
{
"postId": 42,
"id": 207,
"name": "asperiores sed voluptate est",
"email": "Jessika@crystel.ca",
"body": "nulla quos harum commodi\naperiam qui et dignissimos\nreiciendis ut quia est corrupti itaque\nlaboriosam debitis suscipit"
},
...
]
Далее проверим более сложное сочетание — сначала получим список всех альбомов пользователя, а потом посмотрим, какие фотографии принадлежат этому пользователю:
curl "https://jsonplaceholder.typicode.com/users/3/albums"
В ответе будет множество альбомов этомго пользователя. id
в данном случае это идентификатор альбома:
[
{
"userId": 3,
"id": 21,
"title": "repudiandae voluptatem optio est consequatur rem in temporibus et"
},
{
"userId": 3,
"id": 22,
"title": "et rem non provident vel ut"
},
{
"userId": 3,
"id": 23,
"title": "incidunt quisquam hic adipisci sequi"
},
...
]
Зная, что пользователю принадлежит альбом с id=21
, запросим фотографии из этого альбома:
curl "https://jsonplaceholder.typicode.com/albums/21/photos"
Получим массив фотогрфий, начинащийся так:
[
{
"albumId": 21,
"id": 1001,
"title": "velit corrupti odio suscipit rerum",
"url": "https://via.placeholder.com/600/a91759",
"thumbnailUrl": "https://via.placeholder.com/150/a91759"
},
{
"albumId": 21,
"id": 1002,
"title": "eveniet expedita est est amet doloremque facilis velit at",
"url": "https://via.placeholder.com/600/a8d0f4",
"thumbnailUrl": "https://via.placeholder.com/150/a8d0f4"
},
...
]
В последнем примере пришлось сделать два отдельных запроса, чтобы получить один из наборов фотографий пользователя. Как правило, в реальных API поддерживается более глубокая вложенность.
Фильтрация с помощью параметров
До этого мы получали данные, используя уникальный ключ — числовой идентификатор ресурса. Но часто бывает нужно найти ресурс, имея только одну его характеристику. Это можно сделать с помощью запросов с параметрами (query-параметрами). Параметры указываются в URL после имени ресурса следующим образом: https://jsonplaceholder.typicode.com/<ресурс> ? <параметр> = <значение>
.
Используем query-параметры для поиска всех незавершённых задач пользователя с userId=1
. Для этого нужно указать completed=false
для ресурса /todos
:
curl "https://jsonplaceholder.typicode.com/todos?userId=1&completed=false"
Ответ:
[
{
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "quis ut nam facilis et officia qui",
"completed": false
},
{
"userId": 1,
"id": 3,
"title": "fugiat veniam minus",
"completed": false
},
...
]
Попробуйте воспользоваться знанием устройства API, чтобы найти следующее:
- Все альбомы, принадлежащие пользователю с
userId=5
; - Все комментарии к посту с
postId=73
; - Единственного пользователя, у которого
email=Sincere@april.biz
.
POST-запросы
Запросы этого типа используются для передачи данных. Напомню, что в JSONPlaceholder POST-запросы имитируются, ресурсы на самом деле не создаются, но ответ от сервера приходит точно такой, как при выполнении настоящих запросов.
POST-запросы в curl
требуют указания большего колчества параметров:
- Метод, указанный с помощью флага
-X
, после которого указывается URL ресурса; - Тип данных, указанный с помощью флага
-H
; - Тело запроса с помощью флага
-d
. Так как тип данных в данном случае этоapplication/json
, передаваемые данные должны быть в формате JSON.
Попробуем создать новый пост, автором которого будет пользователь с userId=1
:
curl -X POST "https://jsonplaceholder.typicode.com/posts" \
-H "Content-Type: application/json" \
-d '{
"title": "Мой пост",
"body": "Это содержимое поста",
"userId": 1
}'
Так как в API уже есть 100 ресурсов такого типа, у нового поста id=101
. Ответ в формате JSON:
{
"title": "Мой пост",
"body": "Это содержимое поста",
"userId": 1,
"id": 101
}
Далее создадим новый комментарий, отправленный пользователем с именем Иван к первому посту:
curl -X POST "https://jsonplaceholder.typicode.com/comments" \
-H "Content-Type: application/json" \
-d '{
"name": "Иван",
"email": "ivan@example.com",
"body": "Отличная статья!",
"postId": 1
}'
Ответ:
{
"name": "Иван",
"email": "ivan@example.com",
"body": "Отличная статья!",
"postId": 1,
"id": 501
}
Напоследок создадим новую задачу:
curl -X POST "https://jsonplaceholder.typicode.com/todos" \
-H "Content-Type: application/json" \
-d '{
"title": "Изучить POST-запросы",
"completed": true,
"userId": 1
}'
Ответ:
{
"title": "Изучить POST-запросы",
"completed": true,
"userId": 1,
"id": 201
}
На этом заканчивается знакомство с основами HTTP-запросов.
В следующих статьях рассмотрим подробнее другие аспекты клиент-серверного взаимодействия.