Инструменты пользователя

Инструменты сайта


software:development:web:docs:web:api:rest_api

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
software:development:web:docs:web:api:rest_api [2025/10/13 14:14] – создано vladpolskiysoftware:development:web:docs:web:api:rest_api [2025/10/13 14:54] (текущий) – внешнее изменение 127.0.0.1
Строка 104: Строка 104:
   * Старайтесь, чтобы URL-адреса были как можно короче и содержали как можно меньше сегментов   * Старайтесь, чтобы URL-адреса были как можно короче и содержали как можно меньше сегментов
  
 +====Используйте коды HTTP-ответов для указания статуса====
 +Коды ответа являются частью спецификации HTTP. Для описания самых распространенных ситуаций существует большой набор HTTP-ответов.
  
 +Поскольку наши RESTful сервисы следуют спецификации HTTP, наши веб-API должны возвращать коды состояний HTTP. Например, когда ресурс успешно создан с помощью запроса POST, API должен вернуть код состояния HTTP 201. Полный список возможных кодов состояния HTTP c подробным описанием доступен здесь
 +
 +Top 10 кодов состояния HTTP-ответа:
 +===200 ОК===
 +Код, указывающий на успешное выполнение запроса и чаще всего встречающийся на практике
 +===201 CREATED===
 +Ресурс успешно создан (через POST или PUT). Установите заголовок Location со ссылкой на вновь созданный ресурс (при POST). Тело ответа может быть как пустым, так и содержать что-то 204 NO CONTENT
 +Запрос выполнен успешно, но в теле ответа нет данных. Часто используется для операций DELETE и PUT
 +===400 BAD REQUEST===
 +Общая ошибка, когда при выполнении запроса возникает недопустимое состояние. Примеры - ошибки проверки домена, отсутствующие данные и т.д.
 +===401 UNAUTHORIZED===
 +Код ошибки для отсутствующего или недопустимого токена аутентификации
 +===403 FORBIDDEN===
 +Код ошибки, когда пользователь не авторизован для выполнения операции или ресурс недоступен по какой-либо причине (например, ограничения по времени и т.п.)
 +===404 NOT FOUND===
 +Этот код используется, когда запрошенный ресурс не найден. Ресурс не существует, либо была ошибка 401 или 403, которую по соображениям безопасности сервис хочет скрыть
 +===405 METHOD NOT ALLOWED===
 +Используется для указания на то, что запрошенный URL-адрес существует, но используемый HTTP-метод неприменим. Например, POST /users/12345, где API не поддерживает создание ресурсов таким образом (с предоставленным идентификатором). При возврате ошибки 405 должен быть установлен HTTP-заголовок Allow, указывающий на поддерживаемые методы HTTP. В примере выше заголовок выглядел бы как “Allow: GET, PUT, DELETE”
 +===409 CONFLICT===
 +Этот код ошибки отправляется всякий раз, когда выполнение запроса может привести к конфликту ресурсов. Примеры таких ситуаций - двойные записи, например, попытка создать двух клиентов с одинаковой информацией; удаление корневых объектов, когда не поддерживается каскадное удаление
 +===500 INTERNAL SERVER ERROR===
 +Никогда не отправляйте этот код вручную. Это общая ошибка, когда на стороне сервера выбрасывается какое-то исключение. Этот код должен использоваться только для ошибок, которые пользователь не может устранить со своей стороны
 +====XML и JSON====
 +Если вы не работаете в строго стандартизированной и регулируемой отрасли, лучше поддерживать JSON. Но если вас ничто не сковывает, позвольте пользователям выбирать в каком формате получать данные — JSON или XML. У пользователей должна быть возможность переключаться между ними с помощью HTTP-заголовка Accept или просто изменив расширение с .xml на .json.
 +
 +Имейте в виду, что как только мы начинаем говорить о поддержке XML, мы начинаем говорить о валидации, пространствах имен и т.д. Если этого не требует ваша отрасль, избегайте поддержки всех этих усложнений. По крайней мере, вначале. А если в этом функционале нет острой необходимости, то всегда. JSON является простым, лаконичным и функциональным. Сделайте так, чтобы ваш XML выглядел так же, если это возможно.
 +
 +Другими словами, сделайте возвращаемый XML более похожим на JSON — простым и легко читаемым, без сведений о схеме и пространстве имен, содержащим только данные и ссылки. Если ваш XML будет более сложным, стоимость поддержки будет неоправданно большой. Если судить по нашему опыту — никто никогда не отвечает в формате XML. Обрабатывать XML слишком затратно.
 +
 +Обратите внимание, что JSON-Schema предлагает возможности по валидации XML, если вам все-таки нужен такой функционал.
 +
 +====Создавайте детальные ресурсы====
 +Сначала гораздо проще создавать API, которые имитируют основной домен приложения или архитектуру базы данных вашей системы. В конце концов, вы захотите объединить сервисы, которые используют несколько основных ресурсов, чтобы избежать избыточности информации. Позже будет гораздо проще создать большие ресурсы из отдельных ресурсов, чем детальные ресурсы из более крупных составных ресурсов. Упростите себе задачу и начните с небольших, легко определяемых ресурсов, предоставив для них CRUD-функциональность. Ресурсы без лишней информации, ориентированные на конкретные ситуации, можно сделать позже.
 +
 +====Учитывайте связность====
 +Одним из принципов REST является связность через ссылки. Хотя сервисы остаются полезными и без них, API становится более самоописательным, когда в ответе содержатся ссылки. По крайней мере, ссылка “на себя” информирует клиентов, как данные были или могут быть получены. Кроме того, используйте заголовок Location, который должен содержать ссылку на создание ресурса с помощью POST (или PUT). Для коллекций возвращайте в ответе сведения о том, что поддерживается пагинация, а также, как минимум, ссылки “первая”, “последняя”, “следующая” и “предыдущая”.
 +
 +Что касается форматов ссылок, то их существует довольно много.
 +
 +Спецификация HTTP веб-ссылок RFC5988 определяет ссылку следующим образом:
 +
 +Ссылка — это типизированное соединение между двумя ресурсами, идентифицируемыми интернационализированными идентификаторами ресурсов (IRI) [RFC3987]
 +
 +Ссылка состоит из:
 +
 +  * контекстного IRI
 +  * типа ссылки
 +  * целевого IRI
 +  * целевых атрибутов (опционально)
 +Ссылку можно рассматривать как утверждение вида {контекстный IRI} имеет ресурс {типа} в {целевом IRI}, который имеет {целевые атрибуты}.
 +
 +По меньшей мере, размещайте ссылки в HTTP-заголовке Link, как это рекомендовано в спецификации, или используйте JSON-представление данного стиля HTTP-ссылок (например, ссылки в стиле Atom, см. RFC4287). По мере того, как ваш API будет становиться более зрелым, вы сможете использовать более сложные стили ссылок, такие как HAL+JSON, Siren, Collection+JSON и/или JSON-LD и т.д.
 +
 +=====Именование ресурсов=====
 +
 +Кроме правильного использования HTTP глаголов, именование ресурсов, вероятно, самая обсуждаемая и важная концепция для понимания во время создания понятного и легко используемого API для Web-сервиса. Когда ресурсы названы хорошо, API интуитивен и лёгок в использовании. Если же ресурсы названы плохо, тот же самый API может показаться неуклюжим и трудным в понимании и использовании. Ниже приведены несколько подсказок, как продолжить создавать URI ресурсов для нового API.
 +
 +Фактически RESTful API - это всего лишь набор URI, HTTP вызовов к этим URI и некоторое количество представлений ресурсов в формате JSON и/или XML, многие из которых будут содержать перекрестные ссылки. За основу адресации берется покрытие уникальными идентификаторами ресурсов (URI) У каждого ресурса есть свой адрес или URI: вся интересная информация, которую сервер может предоставить, представлена как ресурс. Ограничение однообразия интерфейса частично реализовано с помощью комбинаций URI и HTTP глаголов и их использованием в соответствии со стандартами и конвенциями.
 +
 +Когда вы решаете, какие ресурсы будут в вашей системе, называйте их существительными, в противоположность глаголам, или действиям. Другими словами, URI должен ссылаться на ресурс, а не на действие. Ещё один отличающий фактор - у существительных есть такие свойства, которых нет у глаголов.
 +
 +Ниже приведены примеры ресурсов:
 +
 +  * Пользователи системы.
 +  * Курсы, в которых зарегистрирован студент.
 +  * История сообщений пользователя.
 +  * Пользователь, который подписан на другого пользователя.
 +  * Пользователи, которые подписаны на другого пользователя.
 +  * Статья о верховой езде.
 +
 +Каждый ресурс сервиса должен иметь хотя бы один URI, идентифицирующий его. И лучше всего, когда этот URI имеет смысл и адекватно описывает этот ресурс. URI должны иметь предсказуемую, иерархическую структуру, чтобы увеличить понятность и, как следствие, юзабилити: предсказуемость означает, что они консистентны, иерархичность означает, что у данных есть структура взаимоотношений. Это не принцип и не ограничение REST, но это улучшает API.
 +
 +RESTful API пишут для потребителей. Названия и структура URI должна передавать смысл этим потребителям. Очень часто трудно понять, где должны быть границы, но с пониманием ваших данных вы поймете и то, что имеет смысл возвращать как представление вашим клиентам. Проектируйте для клиентов, а не для ваших данных.
 +
 +Давайте предположим, что мы описываем систему с покупателями, заказами, отдельными позициями, продуктами и т. д. Рассмотрим URI, включенные в описание ресурсов этого сервиса:
 +
 +Примеры
 +
 +<html>
 +<style>
 +  body_new {
 +    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
 +    font-size: 1rem;
 +    font-weight: 400;
 +    line-height: 1.5;
 +    margin: 0;
 +    color: #212529;
 +    background-color: #fff;
 +    -webkit-text-size-adjust: 100%;
 +    -webkit-tap-highlight-color: transparent;
 +  }
 +
 +  .container_new {
 +    margin: 1rem;
 +    padding: 1.5rem;
 +    border: 1px solid #dee2e6;
 +    border-radius: 0.375rem;
 +  }
 +
 +  .tab_new {
 +    display: flex;
 +    flex-direction: column;
 +  }
 +
 +  .tab-nav_new > input[type="radio"] {
 +    display: none;
 +  }
 +
 +  .tab-content_new {
 +    display: none;
 +  }
 +
 +  #content-1:has(~ .tab-nav_new > #tab-btn-1:checked),
 +  #content-2:has(~ .tab-nav_new > #tab-btn-2:checked),
 +  #content-3:has(~ .tab-nav_new > #tab-btn-3:checked) {
 +    display: block;
 +  }
 +
 +  .tab-nav_new {
 +    display: flex;
 +    flex-wrap: wrap;
 +    border-bottom: 1px solid #dee2e6;
 +    margin-bottom: 1rem;
 +    order: -1;
 +  }
 +
 +  .tab-nav_new > label {
 +    display: block;
 +    padding: 0.5rem 1rem;
 +    color: #0d6efd;
 +    text-decoration: none;
 +    background: 0 0;
 +    border: 1px solid transparent;
 +    margin-bottom: -1px;
 +    border-top-left-radius: 0.375rem;
 +    border-top-right-radius: 0.375rem;
 +    -webkit-appearance: button;
 +    transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out;
 +  }
 +
 +  .tab-nav_new > input[type="radio"]:checked + label {
 +    color: #000;
 +    background-color: #fff;
 +    border-color: #dee2e6 #dee2e6 #fff;
 +    cursor: default;
 +  }
 +</style>
 +<body_new>
 +<div class="container1_new">
 +  <div class="tab_new">
 +    <div class="tab-content_new" id="content-1">
 +      Чтобы создать нового покупателя в системе мы используем:</br></br>
 +POST http://www.example.com/customers</br>
 +</br>
 +Чтобы получить информацию о покупателе с ID# 33245:</br></br>
 +GET http://www.example.com/customers/33245 Тот же URI мы используем для PUT и DELETE, чтобы обновлять и удалять, соответственно.</br>
 +</br>
 +Ниже предложены URI для продуктов:</br></br>
 +POST http://www.example.com/products для создания нового продукта.</br>
 +</br></br>
 +GET|PUT|DELETE http://www.example.com/products/66432</br>
 +для чтения, обновления, удаления продукта с ID# 66432, соответственно.</br>
 +</br>
 +Теперь становится весело… Как насчёт создания нового заказа у покупателя? Один вариант - POST http://www.example.com/orders. Это может работать для создания заказа, но здесь, пожалуй, не учитывается покупатель.</br>
 +</br>
 +Поскольку мы хотим создать заказ для покупателя, (заметьте связь), этот URI, очевидно, не так интуитивен, как мог бы быть. Очевидно, что следующий URI предлагает большую ясность: POST http://www.example.com/customers/33245/orders Теперь мы знаем, что создаём заказ для покупателя с ID# 33245.</br>
 +</br>
 +Что же вернет следующее?</br></br>
 +GET http://www.example.com/customers/33245/orders</br>
 +Вероятно, список заказов покупателя #33245. Заметьте: мы можем не поддерживать DELETE или PUT для этого URL, поскольку он оперирует коллекцией.</br>
 +</br>
 +Теперь, продолжая концепцию иерархичности, как насчёт следующего URI?</br></br>
 +POST http://www.example.com/customers/33245/orders/8769/lineitems</br>
 +Это может добавлять отдельную позицию в заказ #8769 (который принадлежит покупателю #33245). Точно! GET на этот URI вернет все отдельные позиции данного заказа. Как бы то ни было, если отдельные позиции нельзя рассматривать только в контексте покупателя, или их можно рассматривать вне его контекста, мы можем предложить POST www.example.com/orders/8769/lineitems.</br>
 +</br>
 +Наряду с этими строками, поскольку может быть несколько URI для заданного ресурса, мы также можем предложить GET http://www.example.com/orders/8769, который возвращает информацию о заказе по его ID без указания ID покупателя</br>
 +</br>
 +Спускаясь глубже по иерархии:</br></br>
 +GET http://www.example.com/customers/33245/orders/8769/lineitems/1</br>
 +Может возвращать только первую отдельную позицию в заказе.</br>
 +</br>
 +К этому моменту вы уже можете видеть, как работает концепция иерархичности. Нет никаких жёстких правил, убедитесь только, что предложенная структура понятна потребителю ваших сервисов. Как и все в ремесле разработки ПО, именование критично для успеха.</br>
 +</br>
 +Взгляните на некоторые широко используемые API, чтобы приобрести навык проектирования и используйте интуицию своих коллег, чтобы улучшить URI ресурсов вашего API. Ниже приведены некоторые примеры API:</br>
 +</br></br>
 +  * Twitter: https://dev.twitter.com/docs/api</br>
 +  * Facebook: http://developers.facebook.com/docs/reference/api/</br>
 +  * LinkedIn: https://developer.linkedin.com/apis</br>
 +    </div>
 +    <div class="tab-content_new" id="content-2">
 +      Пока мы обсуждали некоторые примеры подходящих названий для ресурсов, иногда более информативно увидеть некоторые анти-паттерны. Ниже представлены плохие примеры RESTful URI ресурсов, которые были замечены в "дикой природе." Никогда так не делайте.
 +</br></br>
 +Прежде всего, часто сервисы используют один URI, чтобы определить интерфейс, используя строковые параметры jquery для определения операции, которую нужно выполнить и/или HTTP глагол. Например, чтобы обновить данные покупателя с ID 12345 и получить их в формате JSON может быть использован такой запрос:
 +</br></br>
 +GET http://api.example.com/services?op=update_customer&id=12345&format=json
 +</br></br>
 +Теперь вы не станете так делать. Несмотря на то, что узел URL-адреса 'services' — существительное, он не является самодокументируемым, поскольку иерархия URI не одна и та же для всех запросов. Кроме того, он использует глагол GET, хотя выполняет обновление. Это контринтуитивно, опасно и вызывает много боли у клиентов.
 +</br></br>
 +Вот другой пример, который тоже выполняет обновление данных о покупателе:
 +</br></br>
 +GET http://api.example.com/update_customer/12345
 +</br></br>
 +И его злобный двойник:
 +</br></br>
 +GET http://api.example.com/customers/12345/update
 +</br></br>
 +Вы часто можете увидеть последний запрос в сервисах других разработчиков. Заметим, что разработчики стараются создавать RESTful ресурсы и кое-где заметен прогресс. Но лучше, когда вы можете увидеть глагол в URL. Заметьте также, что нам не нужно использовать фразу 'update' в URL, потому что мы можем довериться HTTP глаголу, чтобы сообщить об этой операции. Проясним, что следующий URL избыточен:
 +</br></br>
 +PUT http://api.example.com/customers/12345/update
 +</br></br>
 +И с PUT, и с 'update' в запросе, мы рискуем запутать потребителей нашего сервиса. Является ли 'update' ресурсом? Мы потратим некоторое время на выяснение этого. Я уверен, вы понимаете.
 +    </div>
 +    <div class="tab-content_new" id="content-3">
 +      Давайте поговорим о споре между плюрализаторами и "сингуларизаторами". Вы не слышали об этом споре? Он существует. Соответственно, всё сводится в следующему вопросу:
 +</br></br>
 +Должны ли узлы URI в иерархии называться существительными в единственном или множественном числе? Например, как должен выглядеть URI для получения данных о покупателе:
 +</br></br>
 +GET http://www.example.com/customer/33245 или GET http://www.example.com/customers/33245
 +</br></br>
 +С обеих точек зрения приведены хорошие аргументы, но общепринятой практикой является плюрализация узлов, чтобы обеспечить согласованность для всех HTTP методов. Этот подход обоснован тем, что покупатели считаются коллекцией внутри сервиса и ID (например, 33245) ссылается на одного покупателя из коллекции.
 +</br></br>
 +Используя это правило, получим следующие URI с множеством узлов (выделено мной):
 +</br></br>
 +GET http://www.example.com/customers/33245/orders/8769/lineitems/1
 +</br></br>
 +ноды 'customers', 'orders', и 'lineitems' использованы во множественном числе.
 +</br></br>
 +Это подразумевает, что вам нужно только два базовых URL для каждой корневой сущности. Один для создания ресурса внутри коллекции и другой для чтения, обновления и удаления ресурса по его идентификатору. Например, для создания (используя покупателей)
 +</br></br>
 +POST http://www.example.com/customers
 +</br></br>
 +А для чтения, обновления и удаления следующий:
 +</br></br>
 +GET|PUT|DELETE http://www.example.com/customers/{id}
 +</br></br>
 +Как было замечено ранее, у ресурса может быть несколько URI, но для минимальных возможностей CRUD'а достаточно всего двух.
 +</br></br>
 +Вы можете спросить: есть ли ситуации, когда плюрализация не имеет смысла. Да, фактически есть. Когда в системе не требуется коллекция. Другими словами, приемлем singleton ресурс. Например, если есть единственный всеобъемлющий конфигурационный ресурс, вы можете использовать существительное в единственном числе, чтобы это отразить:
 +</br></br>
 +GET|PUT|DELETE http://www.example.com/configuration
 +</br></br>
 +Обратите внимание на отсутствие ID и использования глагола POST. Вы скажете, что если бы у каждого покупателя могла быть только одна конфигурация, тогда URL мог бы быть таким:
 +</br></br>
 +GET|PUT|DELETE http://www.example.com/customers/12345/configuration
 +</br></br>
 +Снова нет никакого ID для конфигурации и нет использования глагола POST. Хотя я уверен, что в обоих случаях можно утверждать, что использование POST является допустимым. Ладно, хорошо.
 +    </div>
 +    <div class="tab-nav_new">
 +      <input checked id="tab-btn-1" name="tab-btn" type="radio" value="">
 +      <label for="tab-btn-1">Примеры URI ресурсов</label>
 +      <input id="tab-btn-2" name="tab-btn" type="radio" value="">
 +      <label for="tab-btn-2">Плохие примеры именования ресурсов</label>
 +      <input id="tab-btn-3" name="tab-btn" type="radio" value="">
 +      <label for="tab-btn-3">Множественность</label>
 +    </div>
 +  </div>
 +</div>
 +</body_new>
 +</html>
 +
 +=====Что такое Идемпотентность?=====
 +====Идемпотентность====
 +Идемпотентность - это забавное слово, которое часто выбивает людей из колеи. Идемпотентность кажется иногда запутанной концепцией, по крайней мере, если судить по академическому определению.
 +
 +С точки зрения RESTful-сервиса, операция (или вызов сервиса) идемпотентна тогда, когда клиенты могут делать один и тот же вызов неоднократно при одном и том же результате, работая как “сеттер” в языке программирования. Другими словами, создание большого количества идентичных запросов имеет такой же эффект, как и один запрос. Заметьте, что в то время, как идемпотентные операции производят один и тот же результат на сервере (побочные эффекты), ответ сам по себе может не быть тем же самым (например, состояние ресурса может измениться между запросами).
 +
 +Методы PUT и DELETE по определению идемпотентны. Тем не менее есть один нюанс с методом DELETE. Проблема в том, что успешный DELETE-запрос возвращает статус 200 (OK) или 204 (No Content), но для последующих запросов будет всё время возвращать 404 (Not Found), если только сервис не сконфигурирован так, чтобы “помечать” ресурс как удалённый без его фактического удаления. Как бы то ни было, когда сервис на самом деле удаляет ресурс, следующий вызов не найдёт этот ресурс и вернет 404. Состояние на сервере после каждого вызова DELETE то же самое, но ответы разные.
 +
 +Методы GET, HEAD, OPTIONS и TRACE определены как безопасные, что также делает их идемпотентными. Прочитайте секцию о безопасности ниже.
 +
 +====Безопасность====
 +Некоторые HTTP-методы (например: HEAD, GET, OPTIONS и TRACE) определены как безопасные, это означает, что они предназначены только для получения информации и не должны изменять состояние сервера. Другими словами, они не должны иметь побочных эффектов, за исключением безобидных эффектов, таких как: логирование, кеширование, показ баннерной рекламы или увеличение веб-счетчика. Созданный произвольный GET-запрос, который не учитывает контекст состояния приложения, следует считать безопасным.
 +
 +Упрощенно, безопасность означает, что вызов метода не имеет побочных эффектов. Следовательно, такие (безопасные) запросы клиенты могут безопасно совершать неоднократно, не опасаясь изменить состояние сервера. Это означает, что сервисы должны придерживаться определения безопасности для GET, HEAD, OPTIONS и TRACE операций. Не выполнения этого свойства может приводить в заблуждение потребителя сервиса, а также вызвать проблемы для веб-кеширования, поисковых систем и других автоматизированных агентов, которые непреднамеренно будут изменять состояние сервера.
 +
 +По определению, безопасные операции идемпотентны, так как они приводят к одному и тому же результату на сервере.
 +
 +Безопасные методы реализованы как операции только для чтения. Однако безопасность не означает, что сервер должен возвращать тот же самый результат каждый раз.
 +
 +=====Использование HTTP методов для создания RESTful сервисов=====
 +HTTP глаголы составляют основную часть “единого интерфейса”, ограничивающего и предоставляющего возможность осуществлять действия над существительным-ресурсом.Основными или наиболее часто используемыми HTTP глаголами (или методами, как их иногда называют) являются POST, GET, PUT, и DELETE. Они соответствуют операциям создания чтения, обновления и удаления (или в совокупности - CRUD). Есть еще и другие глаголы они используются реже. Из реже используемых методов выделяются OPTIONS и HEAD
 +
 +Ниже приведена сводная таблица рекомендаций по возвращению значений при использовании основных HTTP глаголов в сочетании с ресурсами URI:
 +
 +|HTTP Глагол |Ресурс (например /customers) |Экземпляр (например /customers/{id})|
 +|GET| 200 (OK), перечень customers. Используется постраничная навигация, сортировка и фильтрация для больших списков.| 200 (OK), конкретный customer. 404 (Not Found), в случае отсутствия экземпляра с указанным ID или если он не корректен (а также, если клиенту непозволительно знать о наличии данного экземпляра).|
 +|PUT| 404 (Not Found), если была попытка обновить/заменить экземпляр во всей коллекции.| 200 (OK) или 204 (No Content). 404 (Not Found), в случае отсутствия экземпляра с указанным ID или если он не корректен (а также, если клиенту непозволительно знать о наличии данного экземпляра).|
 +|PATCH| 405 (Method Not Allowed), если не попытка обновить/заменить всю коллекцию.| 200 (OK) или 204 (No Content). 404 (Not Found), в случае отсутствия экземпляра с указанным ID или если он не корректен (а также, если клиенту непозволительно знать о наличии данного экземпляра).|
 +|POST| 201 (Created), заголовок 'Location' ссылается на /customers/{id}, где ID - идентификатор нового экземпляра.| 404 (Not Found).|
 +|DELETE| 404 (Not Found), если вы хотите удалить всю коллекцию, что крайне не желательно.| 200 (OK) или 204 (No Content). 404 (Not Found), в случае отсутствия экземпляра с указанным ID или если он не корректен (а также, если клиенту непозволительно знать о наличии данного экземпляра).|
 +
 +Ниже приводится более подробное обсуждение основных методов HTTP.
 +
 +<html>
 +<style>
 +  body_new {
 +    font-family: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", "Noto Sans", "Liberation Sans", Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
 +    font-size: 1rem;
 +    font-weight: 400;
 +    line-height: 1.5;
 +    margin: 0;
 +    color: #212529;
 +    background-color: #fff;
 +    -webkit-text-size-adjust: 100%;
 +    -webkit-tap-highlight-color: transparent;
 +  }
 +
 +  .container_new {
 +    margin: 1rem;
 +    padding: 1.5rem;
 +    border: 1px solid #dee2e6;
 +    border-radius: 0.375rem;
 +  }
 +
 +  .tab_new {
 +    display: flex;
 +    flex-direction: column;
 +  }
 +
 +  .tab-nav_new > input[type="radio"] {
 +    display: none;
 +  }
 +
 +  .tab-content_new {
 +    display: none;
 +  }
 +
 +  #content-1:has(~ .tab-nav_new > #tab-btn-1:checked),
 +  #content-2:has(~ .tab-nav_new > #tab-btn-2:checked),
 +  #content-3:has(~ .tab-nav_new > #tab-btn-3:checked),
 +  #content-4:has(~ .tab-nav_new > #tab-btn-4:checked),
 +  #content-5:has(~ .tab-nav_new > #tab-btn-5:checked) {
 +    display: block;
 +  }
 +
 +  .tab-nav_new {
 +    display: flex;
 +    flex-wrap: wrap;
 +    border-bottom: 1px solid #dee2e6;
 +    margin-bottom: 1rem;
 +    order: -1;
 +  }
 +
 +  .tab-nav_new > label {
 +    display: block;
 +    padding: 0.5rem 1rem;
 +    color: #0d6efd;
 +    text-decoration: none;
 +    background: 0 0;
 +    border: 1px solid transparent;
 +    margin-bottom: -1px;
 +    border-top-left-radius: 0.375rem;
 +    border-top-right-radius: 0.375rem;
 +    -webkit-appearance: button;
 +    transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out;
 +  }
 +
 +  .tab-nav_new > input[type="radio"]:checked + label {
 +    color: #000;
 +    background-color: #fff;
 +    border-color: #dee2e6 #dee2e6 #fff;
 +    cursor: default;
 +  }
 +</style>
 +<body_new>
 +<div class="container1_new">
 +  <div class="tab_new">
 +    <div class="tab-content_new" id="content-1">
 +      HTTP метод GET используется для получения (или чтения) представления ресурса. В случае „удачного” (или не содержащего ошибок) адреса, GET возвращается представление ресурса в формате XML или JSON в сочетании с кодом состояния HTTP 200 (OK). В случае наличия ошибок обычно возвращается код 404 (NOT FOUND) или 400 (BAD REQUEST).
 +</br></br>
 +В соответствии спецификации HTTP, GET (так же как и HEAD) запросы используются только для чтения данных, не изменяя их. Таким образом, при соблюдении данного соглашения, они считаются безопасными. То есть они могут использоваться без риска изменения данных, вне зависимости от того, один раз данные были получены, или же 10, или ни разу вовсе. GET (а также HEAD) запросы являются идемпотентными (тождественными), что подразумевает получение идентичных данных при использовании одних и тех же запросов (как при единичном обращении, так и при многократном).
 +</br></br>
 +Не стоит использовать GET для небезопасных операций над данными, при данном запросе они не должны быть модифицированы.
 +</br></br>
 +Примеры:
 +</br></br>
 +GET http://www.example.com/customers/12345</br>
 +GET http://www.example.com/customers/12345/orders</br>
 +GET http://www.example.com/buckets/sample</br></br>
 +    </div>
 +    <div class="tab-content_new" id="content-2">
 +      Метод PUT обычно используется для предоставления возможности обновления ресурса. Тело запроса при отправке PUT-запроса к существующему ресурсу URI должно содержать обновленные данные оригинального ресурса (полностью, или только обновляемую часть).
 +</br></br>
 +Кроме того, PUT может быть использован для создания ресурса, в случае, когда идентификатор ресурса выбирает клиент, а не сервер. Или, если перефразировать — при отправке PUT запроса по адресу, содержащему не существующий идентификатор ресурса. Опять же, стоит помнить, что тело запроса должно быть модификацией оригинального ресурса. Многие считают это запутанным и непонятным. Соответственно, данную возможность метода PUT стоит использовать с осторожностью. Да и при крайней необходимости.
 +</br></br>
 +Для создания новых экземпляров ресурса предпочтительнее использование POST запроса. В данном случае, при создании экземпляра будет предоставлен корректный идентификатор экземпляра ресурса в возвращённых данных об экземпляре.
 +</br></br>
 +При успешном обновлении посредством выполнения PUT запроса возвращается код 200 (или 204 если не был передан какой-либо контент в теле ответа). Если PUT используется для создания экземпляра — обычно возвращают HTTP код 201 при успешном создании. Возвращать данные в ответ на запрос необязательно. Также не обязательно возвращать ссылку на экземпляр ресурса посредством заголовка `Location` по причине того, что клиент и так обладает идентификатором экземпляра ресурса.
 +</br></br>
 +PUT не безопасная операция, так как вследствие её выполнения происходит модификация (или создание) экземпляров ресурса на стороне сервера, но этот метод идемпотентен. Другими словами, создание или обновление ресурса посредством отправки PUT запроса — ресурс не исчезнет, будет располагаться там же, где и был при первом обращении, а также, многократное выполнение одного и того же PUT запроса не изменит общего состояния системы (за исключением первого раза, но это обычно опускают из рассмотрения)
 +</br></br>
 +Если PUT запрос используется для увеличения счётчика просмотра конкретного ресурса — данный запрос уже не считается идемпотентным. Иногда такое происходит и считается достаточным задокументировать тот факт, что вызов не идемпотентен. Однако строго рекомендуется выдерживать идемпотентность PUT запроса.
 +</br></br>
 +Примеры:
 +</br></br>
 +PUT http://www.example.com/customers/12345</br>
 +PUT http://www.example.com/customers/12345/orders/98765</br>
 +PUT http://www.example.com/buckets/secret_stuff</br></br>
 +    </div>
 +    <div class="tab-content_new" id="content-3">
 +      PATCH запрос используется для **модификации** ресурса. PATCH запрос должен содержать только изменяемые данные ресурса, а не все его данные.
 +</br></br>
 +Это напоминает работу PUT запроса, но в теле запроса содержится набор инструкций описывающих как должен быть изменён ресурс, расположенный на сервере, для формирования новой версии. Это означает, что тело PATCH запроса должно содержать не просто изменения ресурса, а представлять из себя описание на языке внесения изменений (patch language) таких как JSON Patch или XML Patch.
 +</br></br>
 +PATCH запрос ни является безопасным, ни идемпотентным. Однако PATСH запрос может быть сформирован таким образом чтобы быть идемпотентным, что в свою очередь помогает предотвратить негативные последствия от коллизий между двумя PATCH запросами к одному и тому же ресурсу в один и тот же промежуток времени. Коллизии нескольких PATCH запросов могут быть более опасными чем коллизии PUT запросов, потому что некоторым форматам изменений необходимо выполняться от известной базовой-точки или ресурс будет поврежден. Клиенты, использующие такой тип внесения изменений, должны использовать условный запрос на проверку изменения ресурса с момента последнего доступа клиента к нему. Например клиент может использовать ETag в заголовке If-Match в самом PATСH запросе.
 +</br></br>
 +Примеры:
 +</br></br>
 +PATCH http://www.example.com/customers/12345</br>
 +PATCH http://www.example.com/customers/12345/orders/98765</br>
 +PATCH http://www.example.com/buckets/secret_stuff</br></br>
 +    </div>
 +        <div class="tab-content_new" id="content-4">
 +      POST запрос наиболее часто используется для создания новых ресурсов. На практике он используется для создания вложенных ресурсов. Другими словами, при создании нового ресурса, POST запрос отправляется к родительскому ресурсу и, таким образом, сервис берет на себя ответственность на установление связи создаваемого ресурса с родительским ресурсом, назначение новому ресурсу ID и т.п.
 +</br></br>
 +При успешном создании ресурса возвращается HTTP код 201, а также в заголовке `Location` передается адрес созданного ресурса.
 +</br></br>
 +POST не является безопасным или идемпотентным запросом. Потому рекомендуется его использование для не идемпотентных запросов. В результате выполнения идентичных POST запросов предоставляются сильно похожие, но не идентичные данные.
 +</br></br>
 +Примеры:
 +</br></br>
 +POST http://www.example.com/customers</br>
 +POST http://www.example.com/customers/12345/orders</br></br>
 +    </div>
 +        <div class="tab-content_new" id="content-5">
 +      DELETE запрос крайне прост для понимания. Он используется для удаления ресурса, идентифицированного конкретным URI (ID).
 +</br></br>
 +При успешном удалении возвращается 200 (OK) код HTTP, совместно с телом ответа, содержащим данные удалённого ресурса (отрицательно сказывается на экономии трафика) или завернутые ответы (Смотрите "Возвращаемые данные"). Также возможно использование HTTP кода 204 (NO CONTENT) без тела ответа.
 +</br></br>
 +Согласно спецификации HTTP, DELETE запрос идемпотентен. Если вы выполняете DELETE запрос к ресурсу, он удаляется. Повторный DELETE запрос к ресурсу закончится также: ресурс удалён. Если DELETE запрос используется для декремента счётчика, DELETE запрос не является идемпотентным. Используйте POST для неидемпотентных операций.
 +</br></br>
 +Тем не менее, существует предостережение об идемпотентности DELETE. Повторный DELETE запрос к ресурсу часто сопровождается 404 (NOT FOUND) кодом HTTP по причине того, что ресурс уже удалён (например из базы данных) и более не доступен. Это делает DELETE операцию не идемпотентной, но это общепринятый компромисс на тот случай, если ресурс был удалён из базы данных, а не помечен, как удалённый.
 +</br></br>
 +Примеры:
 +</br></br>
 +DELETE http://www.example.com/customers/12345</br>
 +DELETE http://www.example.com/customers/12345/orders</br>
 +DELETE http://www.example.com/bucket/sample</br>
 +    </div>
 +    <div class="tab-nav_new">
 +      <input checked id="tab-btn-1" name="tab-btn" type="radio" value="">
 +      <label for="tab-btn-1">GET</label>
 +      <input id="tab-btn-2" name="tab-btn" type="radio" value="">
 +      <label for="tab-btn-2">PUT</label>
 +      <input id="tab-btn-3" name="tab-btn" type="radio" value="">
 +      <label for="tab-btn-3">PATCH</label>
 +      <input id="tab-btn-4" name="tab-btn" type="radio" value="">
 +      <label for="tab-btn-4">POST</label>
 +      <input id="tab-btn-5" name="tab-btn" type="radio" value="">
 +      <label for="tab-btn-5">DELETE</label>
 +    </div>
 +  </div>
 +</div>
 +</body_new>
 +</html>
 +
 +=====Дополнения и Файлы=====
 +[[https://restapitutorial.ru/|Ссылка на оригинальную статью]]
software/development/web/docs/web/api/rest_api.1760354084.txt.gz · Последнее изменение: vladpolskiy