- PVSM.RU - https://www.pvsm.ru -

Автоматизация Для Самых Маленьких. Заметки. RESTful API

Эта статья — одна из обещанных коротких заметок по ходу цикла статей Автоматизация Для Самых Маленьких [1].
Поскольку основным способом взаимодействия с IPAM-системой будет RESTful API, я решил рассказать о нём отдельно.


Воздаю хвалы архитекторам современного мира — у нас есть стандартизированные интерфейсы. Да их много — это минус, но они есть — это плюс.

Эти интерфейсы взаимодействия обрели имя API — Application Programming Interface.

Одним из таких интерфейсов является RESTful API, который и используется для работы с NetBox.

Автоматизация Для Самых Маленьких. Заметки. RESTful API - 1

Если очень просто, то API даёт клиенту набор инструментов, через которые тот может управлять сервером. А клиентом может выступать по сути что угодно: веб-браузер, командная консоль, разработанное производителем приложение, или вообще любое другое приложение, у которого есть доступ к API.

Например, в случае NetBox, добавить новое устройство в него можно следующими способами: через веб-браузер, отправив curl'ом запрос в консоли, использовать Postman, обратиться к библиотеке requests в питоне, воспользоваться SDK pynetbox или перейти в Swagger.

Таким образом, один раз написав единый интерфейс, производитель навсегда освобождает себя от необходимости с каждым новым клиентом договариваться как его подключать (хотя, это самую малость лукавство).

Содержание

  • REST, RESTful, API
  • Структура сообщений HTTP
    • Стартовая строка
    • Заголовки
    • Тело HTTP-сообщения

  • Методы
    • HTTP GET
    • HTTP POST
    • HTTP PUT
    • HTTP PATCH
    • HTTP DELETE

  • Способы работы с RESTful API
    • CURL
    • Postman
    • Python+Requests
    • SDK Pynebtbox
    • SWAGGER

  • Критика REST и альтернативы
  • Полезные ссылки

REST, RESTful, API

Ниже я дам очень упрощённое описание того, что такое REST.

Начнём с того, что RESTful API — это именно интерфейс взаимодействия, основанный на REST, в то время как сам REST (REpresentational State Transfer) — это набор ограничений, используемых для создания WEB-сервисов.

О каких именно ограничениях идёт речь, можно почитать в главе 5 диссертации Роя Филдинга Architectural Styles and the Design of Network-based Software Architectures [2]. Мне же позвольте привести только три наиболее значимых (с моей точки зрения) из них:

  1. В REST-архитектуре используется модель взаимодействия Клиент-Сервер.
  2. Каждый REST-запрос содержит всю информацию, необходимую для его выполнения. То есть сервер не должен помнить ничего о предыдущих запросах клиента, что, как известно, характеризуется словом Stateless — не храним информацию о состоянии.
  3. Единый интерфейс. Реализация приложения отделена от сервиса, который оно предоставляет. То есть пользователь знает, что оно делает и как с ним взаимодействовать, но как именно оно это делает не имеет значения. При изменении приложения, интерфейс остаётся прежним, и клиентам не нужно подстраиваться.

WEB-сервисы, удовлетворяющие всем принципам REST, называются RESTful WEB-services.

А API, который предоставляют RESTful WEB-сервисы, называется RESTful API.

REST — не протокол, а, так называемый, стиль архитектуры (один из). Развиваемому вместе с HTTP Роем Филдингом, REST'у было предназначено использовать HTTP 1.1, в качестве транспорта.

Адрес назначения (или иным словом — объект, или ещё иным — эндпоинт) — это привычный нам URI [3].

Формат передаваемых данных — XML или JSON.

Для этой серии статей на linkmeup развёрнута read-only (для вас, дорогие, читатели) инсталляция NetBox: netbox.linkmeup.ru [4]:45127.

На чтение права не требуются, но если хочется попробовать читать с токеном, то можно воспользоваться этим: API Token: 90a22967d0bc4bdcd8ca47ec490bbf0b0cb2d9c8.

Давайте интереса ради сделаем один запрос:

curl -X GET -H "Authorization: TOKEN 90a22967d0bc4bdcd8ca47ec490bbf0b0cb2d9c8" 
-H "Accept: application/json; indent=4" 
http://netbox.linkmeup.ru:45127/api/dcim/devices/1/

То есть утилитой curl мы делаем GET объекта по адресу netbox.linkmeup.ru [4]:45127/api/dcim/devices/1/ с ответом в формате JSON и отступом в 4 пробела.

Или чуть более академически: GET возвращает типизированный объект devices, являющийся параметром объекта DCIM.

Этот запрос можете выполнить и вы — просто скопируйте себе в терминал.

URL, к которому мы обращаемся в запросе, называется Endpoint. В некотором смысле это конечный объект, с которым мы будем взаимодействовать.
Например, в случае netbox'а список всех endpoint'ов можно получить тут [5].

И ещё обратите внимание на знак / в конце URL — он обязателен.

Вот что мы получим в ответ:

{
"id": 1,
"name": "mlg-host-0",
"display_name": "mlg-host-0",
"device_type": {
    "id": 4,
    "url": "http://netbox.linkmeup.ru/api/dcim/device-types/4/",
    "manufacturer": {
        "id": 4,
        "url": "http://netbox.linkmeup.ru/api/dcim/manufacturers/4/",
        "name": "Hypermacro",
        "slug": "hypermacro"
    },
    "model": "Server",
    "slug": "server",
    "display_name": "Hypermacro Server"
},
"device_role": {
    "id": 1,
    "url": "http://netbox.linkmeup.ru/api/dcim/device-roles/1/",
    "name": "Server",
    "slug": "server"
},
"tenant": null,
"platform": null,
"serial": "",
"asset_tag": null,
"site": {
    "id": 6,
    "url": "http://netbox.linkmeup.ru/api/dcim/sites/6/",
    "name": "Малага",
    "slug": "mlg"
},
"rack": {
    "id": 1,
    "url": "http://netbox.linkmeup.ru/api/dcim/racks/1/",
    "name": "A",
    "display_name": "A"
},
"position": 41,
"face": {
    "value": "front",
    "label": "Front",
    "id": 0
},
"parent_device": null,
"status": {
    "value": "active",
    "label": "Active",
    "id": 1
},
"primary_ip": null,
"primary_ip4": null,
"primary_ip6": null,
"cluster": null,
"virtual_chassis": null,
"vc_position": null,
"vc_priority": null,
"comments": "",
"local_context_data": null,
"tags": [],
"custom_fields": {},
"config_context": {},
"created": "2020-01-14",
"last_updated": "2020-01-14T18:39:01.288081Z"
}

Это JSON (как мы и просили), описывающий device с ID 1: как называется, с какой ролью, какой модели, где стоит итд.

Так будет выглядеть HTTP-запрос:

    GET /api/dcim/devices/1/ HTTP/1.1
    Host: netbox.linkmeup.ru:45127
    User-Agent: curl/7.54.0
    Accept: application/json; indent=4

Так будет выглядеть ответ:

    HTTP/1.1 200 OK
    Server: nginx/1.14.0 (Ubuntu)
    Date: Tue, 21 Jan 2020 15:14:22 GMT
    Content-Type: application/json
    Content-Length: 1638
    Connection: keep-alive
    
    Data

Дамп транзакции [6].

А теперь разберёмся, что же мы натворили.


Структура сообщений HTTP

HTTP-сообщение состоит из трёх частей, только первая из которых является обязательной.

  • Стартовая строка
  • Заголовки
  • Тело сообщения

Стартовая строка

Стартовые строки HTTP-запроса и ответа выглядят по-разному.

HTTP-Запрос

METHOD URI HTTP_VERSION

Метод определяет, какое действие клиент хочет совершить: получить данные, создать объект, обновить его, удалить.
URI — идентификатор ресурса, куда клиент обращается или иными словами путь к ресурсу/документу.
HTTP_VERSION — соответственно версия HTTP. На сегодняшний день для REST это всегда 1.1.

Пример:

GET /api/dcim/devices/1/ HTTP/1.1

HTTP-Ответ

HTTP_VERSION STATUS_CODE REASON_PHRASE

HTTP_VERSION — версия HTTP (1.1).
STATUS_CODE — три цифры кода состояния (200, 404, 502 итд)
REASON_PHRASE — Пояснение (OK, NOT FOUND, BAD GATEWAY итд)

Пример:

HTTP/1.1 200 OK

Заголовки

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

Например, в примере выше в HTTP-запросе это были:

    Host: netbox.linkmeup.ru:45127
    User-Agent: curl/7.54.0
    Accept: application/json; indent=4

В них указано, что

  1. Обращаемся к хосту netbox.linkmeup.ru:45127,
  2. Запрос был сгенерирован в curl,
  3. А принимаем данные в формате JSON с отступом 4.

А вот какие заголовки были в HTTP-ответе:

    Server: nginx/1.14.0 (Ubuntu)
    Date: Tue, 21 Jan 2020 15:14:22 GMT
    Content-Type: application/json
    Content-Length: 1638
    Connection: keep-alive

В них указано, что

  1. Тип сервера: nginx на Ubuntu,
  2. Время формирования ответа,
  3. Формат данных в ответе: JSON
  4. Длина данных в ответе: 1638 байтов
  5. Соединение не нужно закрывать — ещё будут данные.

Заголовки, как вы уже заметили, выглядят как пары имя: значение, разделённые знаком ":".

Полный список возможных заголовков [7].

Тело HTTP-сообщения

Тело используется для передачи собственно данных.

В HTTP-ответе это может быть HTML-страничка, или в нашем случае JSON-объект.

Между заголовками и телом должна быть как минимум одна пустая строка.

При использовании метода GET в HTTP-запросе обычно никакого тела нет, потому что передавать нечего. Но тело есть в HTTP-ответе.

А вот например, при POST уже и в запросе будет тело. Давайте о методах и поговорим теперь.


Методы

Как вы уже поняли, для работы с WEB-сервисами HTTP использует методы. То же самое касается и RESTful API.

Возможные сценарии описываются термином CRUD — Create, Read, Update, Delete.
Вот список наиболее популярных методов HTTP, реализующих CRUD:

  • HTTP GET
  • HTTP POST
  • HTTP PUT
  • HTTP DELETE
  • HTTP PATCH

Методы также называются глаголами, поскольку указывают на то, какое действие производится.

Полный список методов [8].

Давайте на примере NetBox разберёмся с каждым из них.

HTTP GET

Это метод для получения информации.

Так, например, мы забираем список устройств:

curl -H "Accept: application/json; indent=4" 
http://netbox.linkmeup.ru:45127/api/dcim/devices/ 

Метод GET безопасный (safe), поскольку не меняет данные, а только запрашивает.

Он идемпотентный с той точки зрения, что один и тот же запрос всегда возвращает одинаковый результат (до тех пор, пока сами данные не поменялись).

На GET сервер возвращает сообщение с HTTP-кодом и телом ответа (response code и response body).

То есть если всё OK, то код ответа — 200 (OK).
Если URL не найден — 404 (NOT FOUND).
Если что-то не так с самим сервером или компонентами, это может быть 500 (SERVER ERROR) или 502 (BAD GATEWAY).
Все возможные коды ответов [9].

Тело возвращается в формате JSON или XML.

Дамп транзакции [10].

Давайте ещё пару примеров. Теперь мы запросим информацию по конкретному устройству по его имени.

curl -X GET -H "Accept: application/json; indent=4" 
"http://netbox.linkmeup.ru:45127/api/dcim/devices/?name=mlg-leaf-0"

Здесь, чтобы задать условия поиска в URI я ещё указал атритбут объекта (параметр name и его значение mlg-leaf-0). Как вы можете видеть, перед условием и после слэша идёт знак "?", а имя и значение разделяются знаком "=".

Так выглядит запрос.

    GET /api/dcim/devices/?name=mlg-leaf-0 HTTP/1.1
    Host: netbox.linkmeup.ru:45127
    User-Agent: curl/7.54.0
    Accept: application/json; indent=4

Дамп транзакции [11].

Если нужно задать пару условий, то запрос будет выглядеть так:

curl -X GET -H "Accept: application/json; indent=4" 
"http://netbox.linkmeup.ru:45127/api/dcim/devices/?role=leaf&site=mlg"

Здесь мы запросили все устройства с ролью leaf, расположенные на сайте mlg.
То есть два условия отделяются друг от друга знаком "&".

Дамп транзакции [12].

Из любопытного и приятного — если через "&" задать два условия с одним именем, то между ними будет на самом деле не логическое «И», а логическое «ИЛИ».

То есть вот такой запрос и в самом деле вернёт два объекта: mlg-leaf-0 и mlg-spine-0

curl -X GET -H "Accept: application/json; indent=4" 
"http://netbox.linkmeup.ru:45127/api/dcim/devices/?name=mlg-leaf-0&name=mlg-spine-0"

Дамп транзакции [13].

Попробуем обратиться к несуществующему URL.

curl -X GET -H "Accept: application/json; indent=4" 
"http://netbox.linkmeup.ru:45127/api/dcim/IDGAF/"

Дамп транзакции [14].


HTTP POST

POST используется для создания нового объекта в наборе объектов. Или более сложным языком: для создания нового подчинённого ресурса.
То есть, если есть набор devices, то POST позволяет создать новый объект device внутри devices.

Выберем тот же Endpoint и с помощью POST создадим новое устройство.

curl -X POST "http://netbox.linkmeup.ru:45127/api/dcim/devices/" 
-H "accept: application/json"
-H "Content-Type: application/json" 
-H "Authorization: TOKEN a9aae70d65c928a554f9a038b9d4703a1583594f" 
-d "{ "name": "just a simple russian girl", "device_type": 1, "device_role": 1, "site": 3, "rack": 3, "position": 5, "face": "front"}"

Здесь уже появляется заголовок Authorization, содержащий токен, который авторизует запрос на запись, а после директивы -d расположен JSON с параметрами создаваемого устройства:

{
    "name": "just a simple russian girl",
    "device_type": 1,
    "device_role": 1,
    "site": 3,
    "rack": 3,
    "position": 5,
    "face": "front"}

Запрос у вас не сработает, потому что Токен уже не валиден — не пытайтесь записать в NetBox.

В ответ приходит HTTP-ответ с кодом 201 (CREATED) и JSON'ом в теле сообщения, где сервер возвращает все параметры о созданном устройстве.

    HTTP/1.1 201 Created
    Server: nginx/1.14.0 (Ubuntu)
    Date: Sat, 18 Jan 2020 11:00:22 GMT
    Content-Type: application/json
    Content-Length: 1123
    Connection: keep-alive

    JSON

Дамп транзакции [15].

Теперь новым запросом с методом GET можно его увидеть в выдаче:

curl -X GET -H "Accept: application/json; indent=4" 
"http://netbox.linkmeup.ru:45127/api/dcim/devices/?q=russian"

«q» в NetBox'е позволяет найти все объекты, содержащие в своём названии строку, идущую дальше.

POST, очевидно, не является ни безопасным, ни идемпотентным — он наверняка меняет данные, и дважды выполненный запрос приведёт или к созданию второго такого же объекта, или к ошибке.


HTTP PUT

Это метод для изменения существующего объекта. Endpoint для PUT выглядит иначе, чем для POST — в нём теперь содержится конкретный объект.

PUT может возвращать коды 201 или 200.

Важный момент с этим методом: нужно передавать все обязательные атрибуты, поскольку PUT замещает собой старый объект.

Поэтому, если например, просто попытаться добавить атрибут asset_tag нашему новому устройству, то получим ошибку:

curl -X PUT "http://netbox.linkmeup.ru:45127/api/dcim/devices/18/" 
-H "accept: application/json" 
-H "Content-Type: application/json" 
-H "Authorization: TOKEN a9aae70d65c928a554f9a038b9d4703a1583594f" 
-d "{ "asset_tag": "12345678"}"

{"device_type":["This field is required."],"device_role":["This field is required."],"site":["This field is required."]}

Но если добавить недостающие поля, то всё сработает:

curl -X PUT "http://netbox.linkmeup.ru:45127/api/dcim/devices/18/" 
-H "accept: application/json" 
-H "Content-Type: application/json" 
-H "Authorization: TOKEN a9aae70d65c928a554f9a038b9d4703a1583594f" 
-d "{ "name": "just a simple russian girl", "device_type": 1, "device_role": 1, "site": 3, "rack": 3, "position": 5, "face": "front", "asset_tag": "12345678"}"

Дамп транзакции [16].

Обратите внимание на URL здесь — теперь он включает ID устройства, которое мы хотим менять (18).


HTTP PATCH

Этот метод используется для частичного изменения ресурса.
WAT? Спросите вы, а как же PUT?

PUT — изначально существовавший в стандарте метод, предполагающий полную замену изменяемого объекта. Соответственно в методе PUT, как я и писал выше, придётся указать даже те атрибуты объекта, которые не меняются.

А PATCH был добавлен позже и позволяет указать только те атрибуты, которые действительно меняются.

Например:

curl -X PATCH "http://netbox.linkmeup.ru:45127/api/dcim/devices/18/" 
-H "accept: application/json" 
-H "Content-Type: application/json" 
-H "Authorization: TOKEN a9aae70d65c928a554f9a038b9d4703a1583594f" 
-d "{ "serial": "BREAKINGBAD"}"

Здесь также в URL указан ID устройства, но для изменения только один атрибут serial.

Дамп транзакции [17].


HTTP DELETE

Очевидно, удаляет объект.

Пример.

curl -X DELETE "http://netbox.linkmeup.ru:45127/api/dcim/devices/21/" 
-H "accept: application/json" 
-H "Content-Type: application/json" 
-H "Authorization: TOKEN a9aae70d65c928a554f9a038b9d4703a1583594f"

Метод DELETE идемпотентен с той точки зрения, что повторно выполненный запрос уже ничего не меняет в списке ресурсов (но вернёт код 404 (NOT FOUND).

curl -X DELETE "http://netbox.linkmeup.ru:45127/api/dcim/devices/21/" 
-H "accept: application/json" 
-H "Content-Type: application/json" 
-H "Authorization: TOKEN a9aae70d65c928a554f9a038b9d4703a1583594f"

{"detail":"Not found."}


Способы работы с RESTful API

Curl — это, конечно, очень удобно для доблестных воинов CLI, но есть инструменты получше.

Postman

Postman позволяет в графическом интерфейсе формировать запросы, выбирая методы, заголовки, тело, и отображает результат в удобочитаемом виде.

Кроме того запросы и URI можно сохранять и возвращаться к ним позже.

Скачать Postman на оф.сайте [18].

Так мы можем сделать GET:

Автоматизация Для Самых Маленьких. Заметки. RESTful API - 2
Здесь указан Token в GET только для примера.

А так POST:

Автоматизация Для Самых Маленьких. Заметки. RESTful API - 3

Postman служит только для работы с RESTful API.

Например, не пытайтесь через него отправить NETCONF XML, как это делал я на заре своей автоматизационной карьеры.

Один из приятных бонусов специфицированного API в том, что вы можете в Postman импортировать все эндпоинты и их методы как коллекцию.

Для этого в окне Import (File->Import) выберите Import From Link и вставьте в окно URL netbox.linkmeup.ru [4]:45127/api/docs/?format=openapi.

Автоматизация Для Самых Маленьких. Заметки. RESTful API - 4

Далее, всё, что только можно, вы найдёте в коллекциях.

Автоматизация Для Самых Маленьких. Заметки. RESTful API - 5


Python+requests

Но даже через Postman вы, скорее всего, не будете управлять своими Production-системами. Наверняка, у вас будут внешние приложения, которые захотят без вашего участия взаимодействовать с ними.

Например, система генерации конфигурации захочет забрать список IP-интерфейсов из NetBox.
В Python есть чудесная библиотека requests, которая реализует работу через HTTP.
Пример запроса списка всех устройств:

import requests

HEADERS = {'Content-Type': 'application/json', 'Accept': 'application/json'}
NB_URL = "http://netbox.linkmeup.ru:45127"

request_url = f"{NB_URL}/api/dcim/devices/"
devices = requests.get(request_url, headers = HEADERS)
print(devices.json())

Снова добавим новое устройство:

import requests

API_TOKEN = "a9aae70d65c928a554f9a038b9d4703a1583594f"
HEADERS = {'Authorization': f'Token {API_TOKEN}', 'Content-Type': 'application/json', 'Accept': 'application/json'}
NB_URL = "http://netbox.linkmeup.ru:45127"

request_url = f"{NB_URL}/api/dcim/devices/"

device_parameters = {
    "name": "just a simple REQUESTS girl", 
    "device_type": 1, 
    "device_role": 1, 
    "site": 3, 
}
new_device = requests.post(request_url, headers = HEADERS, json=device_parameters)
print(new_device.json())


Python+NetBox SDK

В случае NetBox есть также Python SDK — Pynetbox [19], который представляет все Endpoint'ы NetBox в виде объекта и его атрибутов, делая за вас всю грязную работу по формированию URI и парсингу ответа, хотя и не бесплатно, конечно.

Например, сделаем то же, что и выше, использую pynetbox.
Список всех устройств:

import pynetbox

NB_URL = "http://netbox.linkmeup.ru:45127"
nb = pynetbox.api(NB_URL)

devices = nb.dcim.devices.all()
print(devices)

Добавить новое устройство:

import pynetbox

API_TOKEN = "a9aae70d65c928a554f9a038b9d4703a1583594f"
NB_URL = "http://netbox.linkmeup.ru:45127"
nb = pynetbox.api(NB_URL, token = API_TOKEN)

device_parameters = {
    "name": "just a simple PYNETBOX girl", 
    "device_type": 1, 
    "device_role": 1, 
    "site": 3, 
}
new_device = nb.dcim.devices.create(**device_parameters)
print(new_device)

Документация по Pynetbox [20].


SWAGGER

За что ещё стоит поблагодарить ушедшее десятилетие, так это за спецификации API. Если вы перейдёте по этому пути [5], то попадёте в Swagger UI — документацию по API Netbox.

Автоматизация Для Самых Маленьких. Заметки. RESTful API - 6

На этой странице перечислены все Endpoint'ы, методы работы с ними, возможные параметры и атрибуты и указано, какие из них обязательны. Кроме того описаны ожидаемые ответы.

Автоматизация Для Самых Маленьких. Заметки. RESTful API - 7

На этой же странице можно выполнять интерактивные запросы, кликнув на Try it out.

По какой-от причине swagger в качестве Base URL берёт имя сервера без порта, поэтому функция Try it out не работает в моих примерах со Swagger'ом. Но вы можете попробовать это на собственной инсталляции.

При нажатии на Execute Swagger UI сформирует строку curl, с помощью которой можно аналогичный запрос сделать из командной строки.

В Swagger UI можно даже создать объект:

Автоматизация Для Самых Маленьких. Заметки. RESTful API - 8

Для этого достаточно быть авторизованным пользователем, обладающим нужными правами.

То, что мы видим на этой странице — это Swagger UI — документация, сгенерированная на основе спецификации API.

С трендами на микросервисную архитектуру всё более важным становится иметь стандартизированный API для взаимодействия между компонентами, эндпоинты и методы которого легко определить как человеку, так и приложению, не роясь в исходном коде или PDF-документации.

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

Swagger — это фреймворк и язык спецификации (который ныне переименован в OpenAPI 2.0), позволяющие реализовать эту задачу.
Углубляться в него я не буду.

За бо́льшими деталями сюда:


Критика REST и альтернативы

Существует и такая, да. Не всё в том мире 2000-го года так уже радужно.

Не являясь экспертом, не берусь предметно раскрывать вопрос, но дам ссылку на небесспорную статью на Хабре [25].

Альтернативным интерфейсом взаимодействия компонентов системы сегодня является gRPC. Ему же пророчат большое будущее на ниве новых подходов к работе с сетевым оборудованием. Но о нём мы поговорим когда-то в будущем, когда придёт его черёд.

Можно также взглянуть на многообещающий GraphQL [26], но нам опять же нет нужды с ним работать пока, поэтому остаётся на самостоятельное изучение.


Важно
Токен a9aae70d65c928a554f9a038b9d4703a1583594f был использован только в демонстрационных целях и больше не работает.

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


Полезные ссылки

Спасибы

  • Андрею Панфилову за вычитку и правки
  • Александру Фатину за вычитку и правки

Автор: Марат

Источник [29]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/sistemnoe-administrirovanie/344615

Ссылки в тексте:

[1] Автоматизация Для Самых Маленьких: https://habr.com/ru/search/?q=%5B%D0%B0%D0%B2%D1%82%D0%BE%D0%BC%D0%B0%D1%82%D0%B8%D0%B7%D0%B0%D1%86%D0%B8%D1%8F%20%D0%B4%D0%BB%D1%8F%20%D1%81%D0%B0%D0%BC%D1%8B%D1%85%20%D0%BC%D0%B0%D0%BB%D0%B5%D0%BD%D1%8C%D0%BA%D0%B8%D1%85%5D&target_type=posts

[2] главе 5 диссертации Роя Филдинга Architectural Styles and the Design of Network-based Software Architectures: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm

[3] URI: https://ru.wikipedia.org/wiki/URI

[4] netbox.linkmeup.ru: http://netbox.linkmeup.ru

[5] тут: http://netbox.linkmeup.ru:45127/api/docs/

[6] Дамп транзакции: https://github.com/eucariot/ADSM/blob/master/docs/source/3_ipam_dcim/dumps/http_get_devices.pcapng

[7] Полный список возможных заголовков: https://en.wikipedia.org/wiki/List_of_HTTP_header_fields

[8] Полный список методов: https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Request_methods

[9] Все возможные коды ответов: https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

[10] Дамп транзакции: https://github.com/eucariot/ADSM/blob/master/docs/source/3_ipam_dcim/dumps/http_get_all_devices.pcapng

[11] Дамп транзакции: https://github.com/eucariot/ADSM/blob/master/docs/source/3_ipam_dcim/dumps/http_get_device_by_name.pcapng

[12] Дамп транзакции: https://github.com/eucariot/ADSM/blob/master/docs/source/3_ipam_dcim/dumps/http_get_device_with_double_conditions.pcapng

[13] Дамп транзакции: https://github.com/eucariot/ADSM/blob/master/docs/source/3_ipam_dcim/dumps/http_get_device_with_or_operand.pcapng

[14] Дамп транзакции: https://github.com/eucariot/ADSM/blob/master/docs/source/3_ipam_dcim/dumps/http_get_not_found.pcapng

[15] Дамп транзакции: https://github.com/eucariot/ADSM/blob/master/docs/source/3_ipam_dcim/dumps/http_post_new_device.pcapng

[16] Дамп транзакции: https://github.com/eucariot/ADSM/blob/master/docs/source/3_ipam_dcim/dumps/http_put_asset_tag.pcapng

[17] Дамп транзакции: https://github.com/eucariot/ADSM/blob/master/docs/source/3_ipam_dcim/dumps/http_patch_serial.pcapng

[18] Скачать Postman на оф.сайте: https://www.getpostman.com/downloads/

[19] Pynetbox: https://github.com/digitalocean/pynetbox

[20] Документация по Pynetbox: https://pynetbox.readthedocs.io/en/latest/

[21] API First: https://medium.com/adobetech/three-principles-of-api-first-design-fa6666d9f694

[22] Сайт Swagger: https://swagger.io/docs/specification/

[23] Пример использования: https://justcodeit.ru/swagger-docs-dlya-api-na-laravel/

[24] Wiki проOpen API: https://en.wikipedia.org/wiki/OpenAPI_Specification

[25] статью на Хабре: https://habr.com/ru/post/265845/

[26] GraphQL: https://habr.com/ru/post/326986/

[27] HTTP-методы: https://restfulapi.net/http-methods/

[28] Принципы REST: https://restfulapi.net/rest-architectural-constraints/

[29] Источник: https://habr.com/ru/post/485618/?utm_source=habrahabr&utm_medium=rss&utm_campaign=485618