В программировании часто используется аббревиатура CRUD. Она обозначает четыре базовых операции над информацией:
- Создание
- Чтение
- Обновление
- Удаление
CRUD строят вокруг какой-то сущности. Для этого создают либо интерфейс с формами, либо HTTP API эндпоинты. В этом уроке мы научимся проводить все эти операции на примере сервиса HTTP Server.
Этот сервис создан специально для обучения.
Посмотрим на пример данных для сущности "задача":
Метод | URL | Операция |
---|---|---|
GET | /tasks | Список задач |
GET | /tasks/1 | Информация о задаче |
POST | /tasks | Добавление задачи |
PATCH | /tasks/1 | Обновление задачи |
DELETE | /tasks/1 | Удаление задачи |
Как видите, в URL постоянно повторяется 1
— это идентификатор конкретной задачи. Он будет меняться в зависимости от того, с какой задачей мы работаем прямо сейчас.
Кстати, идентификатор необязательно должен быть числом. Здесь все зависит от того, что бэкенд считает идентификатором и как идентификаторы создаются в базе данных. Часто в качестве идентификатора используют UUID состоящий из цифр, букв и дефисов.
Давайте вернемся к примеру выше и обратим внимание на использование методов HTTP. У методов есть определенный смысл:
- GET нужен для извлечения данных
- POST — для создания и отправки форм
- PATCH — для обновления
- DELETE — для удаления
При этом URL часто остается одним и тем же.
В API важно использовать подходящие методы. Любые HTTP-запросы обрабатываются веб-серверами и промежуточными прокси, которые могут находиться на пути к веб-серверу. И веб-сервер, и прокси знают про особенности HTTP. В зависимости от параметров запроса они могут делать различные оптимизации и кешировать результат.
Кеширование — это такая техника, которая позволяет веб-серверу или прокси сохранить ответ от сервера и отдавать его при следующих запросах без обращения к самому серверу.
Кеширование ускоряет доступ к ресурсам и разгружает серверы. Результат (ответ) на GET запрос можно кэшировать, для ускорения доступа, потому что GET запрос не должен менять данные. Однако другие типы запросов данные менять могут, поэтому один и тот же GET-запрос может возвращать разные ответы, если данные изменились. В этом случае будут закешированы новые данные.
Методы POST, PATCH и DELETE кешировать нельзя — они должны постоянно приходить на сервер, так как они вносят изменения.
Добавление задачи
Попробуем добавить задачу. Для этого по документации HTTP Server нам нужно отправить POST-запрос на эндпоинт https://http.hexlet.app/http-api/tasks.
Подключение через telnet к серверу выполняется через порт 80:
telnet http.hexlet.app 80
Данные можно отправлять в разных форматах, HTML-формой или JSON-файлом. Чтобы использовать JSON, во время подготовки запроса нужно выполнить два шага:
- Указать заголовок Content-Type со значением application/json
- Преобразовать данные в JSON
В итоге запрос будет выглядеть так:
POST /http-api/tasks HTTP/1.1
HOST: http.hexlet.app
Content-Length: 53
Content-Type: application/json
{"title":"new task","description":"task description"}
Есть несколько возможных вариантов ответа от сервера:
- Код 201 — ресурс успешно создан
- Код 422 — ошибка валидации
- Код 406 — некорректные данные или неверный формат
Подробнее можно прочитать в гайде по HTTP-кодам. Большая часть из них может встречаться с любым HTTP-методом.
Обновление задачи
Для обновления задачи мы должны отправить PATCH-запрос на эндпоинт https://http.hexlet.app/http-api/tasks/:id. Обновлять можно любой набор параметров, не обязательно сразу все:
PATCH /http-api/tasks/1 HTTP/1.1
HOST: http.hexlet.app
Content-Length: 21
Content-Type: application/json
{"title":"new title"}
Если все прошло успешно, то возможны два варианта ответа:
- Код 200 с какими-то данными — например, JSON с обновленными данными ресурса
- Код 204 — нет тела ответа
Удаление задачи
Для удаления задачи мы должны отправить DELETE-запрос на эндпоинт https://http.hexlet.app/http-api/tasks/:id. Тела запроса в таком случае нет, потому что все понятно из адреса запроса:
DELETE /http-api/tasks/1 HTTP/1.1
HOST: http.hexlet.app
Если все прошло успешно, то возможны два варианта ответа:
- Код 200 и какие-то данные
- Код 204 и пустое тело ответа
Идемпотентность
Когда мы работаем с API, очень важна идемпотентность запросов. Это свойство указывает, насколько безопасно выполнять HTTP-вызов повторно. Идемпотентный запрос приводит к одному и тому же результату независимо от количества сделанных вызовов.
Для примера возьмем эндпоинт /tasks. Он возвращает список задач и ничего не меняет на сервере. Каждый новый вызов этого эндпоинта возвращает идентичный список задач — значит, это идемпотентный запрос.
Список задач может поменяться, если его меняют где-то в другом месте. Но даже это не поменяет идемпотентность GET-запроса на /tasks, ведь он сам ничего не меняет.
А вот POST-запрос — точно не идемпотентный. Каждый вызов /tasks имеет два исхода:
- добавляет новую задачу, хотя и с теми же самыми данными
- возвращает ошибку, если на сервере добавлена проверка на уникальность каких-то данных
Именно поэтому при отправке форм после обновления страницы браузер всегда спрашивает, точно ли мы хотим выполнить этот запрос повторно.
По стандарту PATCH тоже не идемпотентный, хотя на практике чаще его делают идемпотентным. Но на это уже не могут рассчитывать браузеры или веб-серверы, потому что они не знают про специфику конкретных приложений.
Самое интересное — это DELETE. По стандарту он идемпотентный, то есть повторное удаление уже удаленного ресурса должно возвращать код 204 по спецификации HTTP. На практике об этом знают далеко не все программисты, поэтому обычно повторное удаление приводит к ошибке 404.
Идемпотентность по стандарту закреплена за методами HTTP в спецификации. Но на практике все может работать иначе. Нельзя с уверенностью сказать, насколько конкретное HTTP API соответствует этим правилам. Все зависит от разработчиков, которые создавали его.
Самостоятельная работа
Подключитесь к "HTTP Server" с помощью команды:
telnet http.hexlet.app 80
Выполните все четыре CRUD-операции для Tasks. Введите строку запроса и заголовок host
.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
- Статья «Как учиться и справляться с негативными мыслями»
- Статья «Ловушки обучения»
- Статья «Сложные простые задачи по программированию»
- Вебинар «Как самостоятельно учиться»
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.