Опубликовано: :: Теги: ,

Ключевой процесс в веб-разработке — это обмен данными через сеть. Практически любое взаимодействие в IT-системах — от просмотра страницы до развертывания приложения — строится на одном и том же: клиент запрашивает данные → сервер отвечает → клиент обрабатывает и отображает данные.

В серии статей мы пошагово разберём этот процесс, чтобы вы не просто видели результат, а понимали, что происходит на каждом этапе. Понимание этих процессов важно для технического писателя, который работает с продуктами для разработчиков, облачными сервисами или платформенными решениями.

Я буду ссылаться на теоретические материалы из журнала Код, принадлежащего Яндекс Практикуму. В статьях из этого цикла делается упор на практику, а ссылки на внешние материалы помогут получить необходимый контекст. Вы можете ознакомиться с соответствующей теорией на любом ресурсе по вашему выбору, «Код» выбран исключительно из соображений удобства.

В серии будет три статьи, в которых разберем следующее:

  1. Увидим, как устроено клиент-серверное взаимодействие;
  2. Понаблюдаем за тем, как браузер получает и отображает данные, а также изучим структуру веб-страниц;
  3. Развернем собственный локальный сервер, чтобы почувствовать, как работает веб изнутри.

В первой статье мы познакомимся с основой основ — запросом к 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-запросом.

  1. Метод и путь. Пример: GET /api/v1/users

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

  • Host: адрес хоста и, опционально, номер порта;
  • Content-Type: тип данных в теле запроса (application/json);
  • Authorization: токен доступа;
  • Accept: какие форматы ответа ожидает клиент;
  1. Тело (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 ресурсов:

РесурсПутьКоличество
Посты/posts100
Комментарии/comments500
Альбомы/albums100
Фото/photos5000
Задачи/todos200
Пользователи/users10

Ссылка на первый пост выглядит так: 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, чтобы найти следующее:

  1. Все альбомы, принадлежащие пользователю с userId=5;
  2. Все комментарии к посту с postId=73;
  3. Единственного пользователя, у которого email=Sincere@april.biz.

POST-запросы

Запросы этого типа используются для передачи данных. Напомню, что в JSONPlaceholder POST-запросы имитируются, ресурсы на самом деле не создаются, но ответ от сервера приходит точно такой, как при выполнении настоящих запросов.

POST-запросы в curl требуют указания большего колчества параметров:

  1. Метод, указанный с помощью флага -X, после которого указывается URL ресурса;
  2. Тип данных, указанный с помощью флага -H;
  3. Тело запроса с помощью флага -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-запросов.

В следующих статьях рассмотрим подробнее другие аспекты клиент-серверного взаимодействия.