1 added
1 removed
Original
2026-01-01
Modified
2026-02-26
1
<p>В программировании часто используется аббревиатура<a>CRUD</a>. Она обозначает четыре базовых операции над информацией:</p>
1
<p>В программировании часто используется аббревиатура<a>CRUD</a>. Она обозначает четыре базовых операции над информацией:</p>
2
<ul><li>Создание</li>
2
<ul><li>Создание</li>
3
<li>Чтение</li>
3
<li>Чтение</li>
4
<li>Обновление</li>
4
<li>Обновление</li>
5
<li>Удаление</li>
5
<li>Удаление</li>
6
</ul><p>CRUD строят вокруг какой-то сущности. Для этого создают либо интерфейс с формами, либо HTTP API эндпоинты. В этом уроке мы научимся проводить все эти операции на примере сервиса<a>HTTP Server</a>.</p>
6
</ul><p>CRUD строят вокруг какой-то сущности. Для этого создают либо интерфейс с формами, либо HTTP API эндпоинты. В этом уроке мы научимся проводить все эти операции на примере сервиса<a>HTTP Server</a>.</p>
7
<p>Этот сервис создан специально для обучения.</p>
7
<p>Этот сервис создан специально для обучения.</p>
8
<p>Посмотрим на пример данных для сущности "задача":</p>
8
<p>Посмотрим на пример данных для сущности "задача":</p>
9
<p>Как видите, в URL постоянно повторяется 1 - это идентификатор конкретной задачи. Он будет меняться в зависимости от того, с какой задачей мы работаем прямо сейчас.</p>
9
<p>Как видите, в URL постоянно повторяется 1 - это идентификатор конкретной задачи. Он будет меняться в зависимости от того, с какой задачей мы работаем прямо сейчас.</p>
10
<p>Кстати, идентификатор необязательно должен быть числом. Здесь все зависит от того, что бэкенд считает идентификатором и как идентификаторы создаются в базе данных. Часто в качестве идентификатора используют<a>UUID</a>состоящий из цифр, букв и дефисов.</p>
10
<p>Кстати, идентификатор необязательно должен быть числом. Здесь все зависит от того, что бэкенд считает идентификатором и как идентификаторы создаются в базе данных. Часто в качестве идентификатора используют<a>UUID</a>состоящий из цифр, букв и дефисов.</p>
11
<p>Давайте вернемся к примеру выше и обратим внимание на использование методов HTTP. У методов есть определенный смысл:</p>
11
<p>Давайте вернемся к примеру выше и обратим внимание на использование методов HTTP. У методов есть определенный смысл:</p>
12
<ul><li>GET нужен для извлечения данных</li>
12
<ul><li>GET нужен для извлечения данных</li>
13
<li>POST - для создания и отправки форм</li>
13
<li>POST - для создания и отправки форм</li>
14
<li>PATCH - для обновления</li>
14
<li>PATCH - для обновления</li>
15
<li>DELETE - для удаления</li>
15
<li>DELETE - для удаления</li>
16
</ul><p>При этом URL часто остается одним и тем же.</p>
16
</ul><p>При этом URL часто остается одним и тем же.</p>
17
-
<p>В API важно использовать подходящие методы. Любые HTTP-запросы обрабатываются веб-серверами и промежуточными прокси, которые могут находиться на пути к веб-серверу. И веб-сервер, и прокси знают про особенности HTTP. В зависимости от параметров запроса они могут делать разли��ные оптимизации и кешировать результат.</p>
17
+
<p>В API важно использовать подходящие методы. Любые HTTP-запросы обрабатываются веб-серверами и промежуточными прокси, которые могут находиться на пути к веб-серверу. И веб-сервер, и прокси знают про особенности HTTP. В зависимости от параметров запроса они могут делать различные оптимизации и кешировать результат.</p>
18
<p><strong>Кеширование</strong>- это такая техника, которая позволяет веб-серверу или прокси сохранить ответ от сервера и отдавать его при следующих запросах без обращения к самому серверу.</p>
18
<p><strong>Кеширование</strong>- это такая техника, которая позволяет веб-серверу или прокси сохранить ответ от сервера и отдавать его при следующих запросах без обращения к самому серверу.</p>
19
<p>Кеширование ускоряет доступ к ресурсам и разгружает серверы. Результат (ответ) на GET запрос можно кэшировать, для ускорения доступа, потому что GET запрос не должен менять данные. Однако другие типы запросов данные менять могут, поэтому один и тот же GET-запрос может возвращать разные ответы, если данные изменились. В этом случае будут закешированы новые данные.</p>
19
<p>Кеширование ускоряет доступ к ресурсам и разгружает серверы. Результат (ответ) на GET запрос можно кэшировать, для ускорения доступа, потому что GET запрос не должен менять данные. Однако другие типы запросов данные менять могут, поэтому один и тот же GET-запрос может возвращать разные ответы, если данные изменились. В этом случае будут закешированы новые данные.</p>
20
<p>Методы POST, PATCH и DELETE кешировать нельзя - они должны постоянно приходить на сервер, так как они вносят изменения.</p>
20
<p>Методы POST, PATCH и DELETE кешировать нельзя - они должны постоянно приходить на сервер, так как они вносят изменения.</p>
21
<h2>Добавление задачи</h2>
21
<h2>Добавление задачи</h2>
22
<p>Попробуем добавить задачу. Для этого по<a>документации HTTP Server</a>нам нужно отправить POST-запрос на эндпоинт<em><a>https://http.hexlet.app/http-api/tasks</a></em>.</p>
22
<p>Попробуем добавить задачу. Для этого по<a>документации HTTP Server</a>нам нужно отправить POST-запрос на эндпоинт<em><a>https://http.hexlet.app/http-api/tasks</a></em>.</p>
23
<p>Подключение через telnet к серверу выполняется через порт 80:</p>
23
<p>Подключение через telnet к серверу выполняется через порт 80:</p>
24
<p>Данные можно отправлять в разных форматах, HTML-формой или JSON-файлом. Чтобы использовать JSON, во время подготовки запроса нужно выполнить два шага:</p>
24
<p>Данные можно отправлять в разных форматах, HTML-формой или JSON-файлом. Чтобы использовать JSON, во время подготовки запроса нужно выполнить два шага:</p>
25
<ol><li>Указать заголовок<em>Content-Type</em>со значением<em>application/json</em></li>
25
<ol><li>Указать заголовок<em>Content-Type</em>со значением<em>application/json</em></li>
26
<li>Преобразовать данные в JSON</li>
26
<li>Преобразовать данные в JSON</li>
27
</ol><p>В итоге запрос будет выглядеть так:</p>
27
</ol><p>В итоге запрос будет выглядеть так:</p>
28
<p>Есть несколько возможных вариантов ответа от сервера:</p>
28
<p>Есть несколько возможных вариантов ответа от сервера:</p>
29
<ul><li>Код<em>201</em>- ресурс успешно создан</li>
29
<ul><li>Код<em>201</em>- ресурс успешно создан</li>
30
<li>Код<em>422</em>- ошибка валидации</li>
30
<li>Код<em>422</em>- ошибка валидации</li>
31
<li>Код<em>406</em>- некорректные данные или неверный формат</li>
31
<li>Код<em>406</em>- некорректные данные или неверный формат</li>
32
</ul><p>Подробнее можно прочитать<a>в гайде по HTTP-кодам</a>. Большая часть из них может встречаться с любым HTTP-методом.</p>
32
</ul><p>Подробнее можно прочитать<a>в гайде по HTTP-кодам</a>. Большая часть из них может встречаться с любым HTTP-методом.</p>
33
<h2>Обновление задачи</h2>
33
<h2>Обновление задачи</h2>
34
<p>Для обновления задачи мы должны отправить PATCH-запрос на эндпоинт<em><a>https://http.hexlet.app/http-api/tasks/:id</a></em>. Обновлять можно любой набор параметров, не обязательно сразу все:</p>
34
<p>Для обновления задачи мы должны отправить PATCH-запрос на эндпоинт<em><a>https://http.hexlet.app/http-api/tasks/:id</a></em>. Обновлять можно любой набор параметров, не обязательно сразу все:</p>
35
<p>Если все прошло успешно, то возможны два варианта ответа:</p>
35
<p>Если все прошло успешно, то возможны два варианта ответа:</p>
36
<ul><li>Код<em>200</em>с какими-то данными - например, JSON с обновленными данными ресурса</li>
36
<ul><li>Код<em>200</em>с какими-то данными - например, JSON с обновленными данными ресурса</li>
37
<li>Код<em>204</em>- нет тела ответа</li>
37
<li>Код<em>204</em>- нет тела ответа</li>
38
</ul><h2>Удаление задачи</h2>
38
</ul><h2>Удаление задачи</h2>
39
<p>Для удаления задачи мы должны отправить DELETE-запрос на эндпоинт<em><a>https://http.hexlet.app/http-api/tasks/:id</a></em>. Тела запроса в таком случае нет, потому что все понятно из адреса запроса:</p>
39
<p>Для удаления задачи мы должны отправить DELETE-запрос на эндпоинт<em><a>https://http.hexlet.app/http-api/tasks/:id</a></em>. Тела запроса в таком случае нет, потому что все понятно из адреса запроса:</p>
40
<p>Если все прошло успешно, то возможны два варианта ответа:</p>
40
<p>Если все прошло успешно, то возможны два варианта ответа:</p>
41
<ul><li>Код<em>200</em>и какие-то данные</li>
41
<ul><li>Код<em>200</em>и какие-то данные</li>
42
<li>Код<em>204</em>и пустое тело ответа</li>
42
<li>Код<em>204</em>и пустое тело ответа</li>
43
</ul><h2>Идемпотентность</h2>
43
</ul><h2>Идемпотентность</h2>
44
<p>Когда мы работаем с API, очень важна<strong>идемпотентность запросов</strong>. Это свойство указывает, насколько безопасно выполнять HTTP-вызов повторно. Идемпотентный запрос приводит к одному и тому же результату независимо от количества сделанных вызовов.</p>
44
<p>Когда мы работаем с API, очень важна<strong>идемпотентность запросов</strong>. Это свойство указывает, насколько безопасно выполнять HTTP-вызов повторно. Идемпотентный запрос приводит к одному и тому же результату независимо от количества сделанных вызовов.</p>
45
<p>Для примера возьмем эндпоинт<em>/tasks</em>. Он возвращает список задач и ничего не меняет на сервере. Каждый новый вызов этого эндпоинта возвращает идентичный список задач - значит, это<strong>идемпотентный запрос</strong>.</p>
45
<p>Для примера возьмем эндпоинт<em>/tasks</em>. Он возвращает список задач и ничего не меняет на сервере. Каждый новый вызов этого эндпоинта возвращает идентичный список задач - значит, это<strong>идемпотентный запрос</strong>.</p>
46
<p>Список задач может поменяться, если его меняют где-то в другом месте. Но даже это не поменяет идемпотентность GET-запроса на<em>/tasks</em>, ведь он сам ничего не меняет.</p>
46
<p>Список задач может поменяться, если его меняют где-то в другом месте. Но даже это не поменяет идемпотентность GET-запроса на<em>/tasks</em>, ведь он сам ничего не меняет.</p>
47
<p>А вот POST-запрос - точно не идемпотентный. Каждый вызов<em>/tasks</em>имеет два исхода:</p>
47
<p>А вот POST-запрос - точно не идемпотентный. Каждый вызов<em>/tasks</em>имеет два исхода:</p>
48
<ul><li>добавляет новую задачу, хотя и с теми же самыми данными</li>
48
<ul><li>добавляет новую задачу, хотя и с теми же самыми данными</li>
49
<li>возвращает ошибку, если на сервере добавлена проверка на уникальность каких-то данных</li>
49
<li>возвращает ошибку, если на сервере добавлена проверка на уникальность каких-то данных</li>
50
</ul><p>Именно поэтому при отправке форм после обновления страницы браузер всегда спрашивает, точно ли мы хотим выполнить этот запрос повторно.</p>
50
</ul><p>Именно поэтому при отправке форм после обновления страницы браузер всегда спрашивает, точно ли мы хотим выполнить этот запрос повторно.</p>
51
<p>По стандарту PATCH тоже не идемпотентный, хотя на практике чаще его делают идемпотентным. Но на это уже не могут рассчитывать браузеры или веб-серверы, потому что они не знают про специфику конкретных приложений.</p>
51
<p>По стандарту PATCH тоже не идемпотентный, хотя на практике чаще его делают идемпотентным. Но на это уже не могут рассчитывать браузеры или веб-серверы, потому что они не знают про специфику конкретных приложений.</p>
52
<p>Самое интересное - это DELETE. По стандарту он идемпотентный, то есть повторное удаление уже удаленного ресурса должно возвращать код<em>204</em>по спецификации HTTP. На практике об этом знают далеко не все программисты, поэтому обычно повторное удаление приводит к ошибке<em>404</em>.</p>
52
<p>Самое интересное - это DELETE. По стандарту он идемпотентный, то есть повторное удаление уже удаленного ресурса должно возвращать код<em>204</em>по спецификации HTTP. На практике об этом знают далеко не все программисты, поэтому обычно повторное удаление приводит к ошибке<em>404</em>.</p>
53
<p>Идемпотентность по стандарту закреплена за методами HTTP в спецификации. Но на практике все может работать иначе. Нельзя с уверенностью сказать, насколько конкретное HTTP API соответствует этим правилам. Все зависит от разработчиков, которые создавали его.</p>
53
<p>Идемпотентность по стандарту закреплена за методами HTTP в спецификации. Но на практике все может работать иначе. Нельзя с уверенностью сказать, насколько конкретное HTTP API соответствует этим правилам. Все зависит от разработчиков, которые создавали его.</p>