Протокол HTTP

Начинаем работать с requests

И так начнем с установки библиотеки requests. Для этого выполните в терминале консоли следующую команду:

$ pip install requests

Если же вы предпочитаете использовать Pipenv для управления пакетами Python, то можете запустить на исполнение следующую команду:

$ pipenv install requests

Установка библиотеки requests в операционной системе Windows и Linux практически не отличаются. В сети достаточно материалов, в которых описан принцип работы с пакетами Python в обеих системах. Поэтому в этой статье касаться этих вопросов мы далее не будем.

После того, как мы установили requests, мы можем ее использовать в своем приложении. Импорт библиотеки requests в ваш код выглядит следующим образом:

import requests

Postman

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

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

Python netbox sdk

В случае NetBox есть также Python SDK —

, который представляет все Endpoint’ы NetBox в виде объекта и его атрибутов, делая за вас всю грязную работу по формированию URI и парсингу ответа, хотя и не бесплатно, конечно.

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

Python requests

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

Rest, restful, api

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

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

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

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

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

RESTful WEB-services

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

Swagger

За что ещё стоит поблагодарить ушедшее десятилетие, так это за спецификации API. Если вы перейдёте по

, то попадёте в Swagger UI — документацию по API Netbox.

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

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

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

При нажатии на

Execute

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

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

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

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

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

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

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

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

Авторизация

Если ресурс требует авторизации пользователя, то сервер в ответ на запрос может вернуть код ответа 401 Unauthorized и строку заголовка с указанием области доступа для которой требуется авторизация

WWW-Authenticate: Basic realm="WallyWorld

Чтобы получить права доступа, клиент посылает в последующих запросах идентификатор пользователя и пароль, разделенные символом двоеточия “:”. Строка авторизации кодируется в base64.

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ##

В реальной жизни используется тип авторизации Basic и NTLM.

Аутентификация

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

Заголовки запроса

В запросе клиент должен передать URI запрашиваемого документа. Это может быть сделано в абсолютной или относительной форме. В первом случае в состав URI должны входить название протокола и имя сервера.

Инспектируем отправленный запрос

Когда вы делаете запрос, библиотека requests предварительно готовит запрос, прежде чем отправить его на целевой сервер. Подготовка запроса включает в себя такие вещи, как проверка корректности заголовков и сериализация содержимого в формате JSON.

Вы можете просмотреть содержимое подготовленного к отправке запроса, используя объект типа PreparedRequest, обратившись к свойству объекта Response.request:

Использование механизма сессий (session)

Для организации сессионного взаимодействия вашего приложения с сервером используется объект Session, который позволяет сохранять необходимые настройки для отправки данных от запроса к запросу в течение всей текущей сессии. То есть он сохраняет и задает содержимое файлов cookie во всех запросах, сформированных с использованием текущего экземпляра объекта Session, и гарантирует использование выделенного пула соединений при дальнейшем взаимодействии с сервером. Объект Sesson поддерживает любые методы запросов из состава API requests.

И так давайте сохраним некоторые данные cookie в запросе:

Какой метод использовать get или post, чем отличаются методы

Основное отличие метода GET от POST в способе передачи данных.

Код состояния запроса (status codes)

Первым битом информации, которую вы можете получить от объекта ответа Response, является код состояния запроса к серверу status codes. Код состояния информирует вас о статусе нашего запроса.

Например, статус 200 OK означает, что ваш запрос был успешным, а статус 404 NOT FOUND означает, что искомый ресурс не найден. Существует много других кодов состояния запроса, которые могут дать вам более детальное представление о том, что же все таки произошло с отправленным запросом.

Используя свойство объекта response.status_code, мы можем получить доступ к коду состояния ответа, который вернул удаленный сервер:

>>> response.status_code
200

При обращении к свойству .status_code мы получили значение 200, что означает, что наш запрос был успешным, и сервер отправил нам данные, которые мы запрашивали.

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

if response.status_code == 200:
    print('Success!')
elif response.status_code == 404:
    print('Not Found.')

В соответствии с логикой этого примера кода, если сервер возвращает код состояния 200, то наша программа напечатает «Success!». Если же — 404, то напечатает “Not Found”.

Библиотека requests существенно упрощает процесс взаимодействия вашего приложения с сервером. Однако необходимо знать ее некоторые довольно специфические особенности. Так например, если мы используем экземпляр объекта Response в условном выражении, то его логическое значение приравнивается к True, если был получен код состояния запроса в диапазоне от 200 до 400, и только в противном случае False.

Поэтому мы можем упростить последний пример, переписав код оператора if следующим образом:

if response:
    print('Success!')
else:
    print('An error has occurred.')

Маленькая техническая деталь: этот тест на истинность значения показал такой результат возможным, так как в объекте Response специальный метод класса __bool__()переопределен.

Это означает то, что поведение по умолчанию объекта Response при вычислении его логического значения было переопределено для процедуры проверки кода состояния запроса.

Имейте в виду, что этот способ проверки не гарантирует, что код состояния вашего запроса успешен и равен 200. Причиной прохождения проверки на истинность является то, что запрос может получать и другие “успешные” коды состояния в диапазоне от 200 до 400.

Такие, например, как 204 NO CONTENT и 304 NOT MODIFIED, которые также можно считать в определенном смысле “успешными”, так как они определяют некоторый успешно обработанный сервером ответ на запрос. Например, код 204 информирует нас, что запрос был успешным, но тело сообщения ответа сервера не ничего не содержит.

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

Количество повторов запроса

В случае если ваш запрос по той или иной причине был неудачен, то вы можете указать приложению повторить тот же запрос заданное число раз. Однако requests не будет это делать для вас по умолчанию. Чтобы использовать эту возможность, необходимо реализовать свой так называемый транспортный адаптер Transport Adapter.

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

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

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

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

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

Логические ошибки

400 Bad Request Сервер обнаружил в запросе клиента синтаксическую ошибку. 
401 Unauthorized    Требуется пароль.
403 Forbidden       Доступ к документу запрещен
404 Not Found   Документ по указанному URI не существует. 
407 Proxy Authentication Required   Требуется пароль к proxy-серверу.

Метод get

GET – это запрос к серверу, который ничего не изменяет на сервере, например, выполняет считывание записи из БД.

В URL кодируются параметры запроса. Сначала идут позиционные параметры, разделенные знаком ‘/’, а затем, после символа ‘&’ – именованные в виде пар ключ-значение. Пары отделяются друг от друга амперсандом ‘&’. Например:

Метод head

Метод HEAD аналогичен методу GET, за исключением того, что сервер ничего не посылает в информационной части ответа. Метод HEAD запрашивает только информацию заголовка о файле или ресурсе. Этот метод используется, когда клиент хочет получить информацию о документе, не получая его. Например, клиента может интересовать:

Некоторые заголовки не являются обязательными и могут отсутствовать в ответе сервера.

Метод post

Метод POST это запрос к серверу, который изменяет состояние сервера, например вносит запись в БД.

Параметры запроса в методе POST могут передаваться в теле запроса. В этом случае их общая длина ничем не ограничена.

Объект сессии session

До сих пор мы имели дело с сетевыми интерфейсами запросов и API высокого уровня, такими как методы get() и post(). Эти методы абстрагирует пользователя от того, что происходит “под капотом” библиотеки, когда мы отправляем запросы.

Одну из основных ролей при абстрагировании пользователя от деталей работы библиотеки, играет класс Session. Если вы хотите осуществлять непосредственный контроль над выполнением запросов, а так же повысить их производительность, то вам необходимо использовать все возможности экземпляров класса Session.

Как мы уже знаем, сессии используются для сохранения некоторого набора настроек от запроса к запросу при обращении к какое-либо удаленной службе. Например, если вы хотите использовать одни и те же данные аутентификации в течение определенного периода времени для отправки нескольких запросов, то можете использовать сессии следующим образом:

Ответ (response)

Объект Response является мощным средством для просмотра содержимого и обработки результатов наших запросов. Давайте пошлем, рассмотренный нами выше, запрос GET еще раз, но в этот раз сохраним принятое значение с объектом ответа в переменной, и затем поближе познакомиться с его атрибутами (свойствами), а также поведением:

Ошибки сервера

500 Internal Server Error   При обработке запроса на один из компонентов сервера аварийно завершился. 
501 Not Implemented     Клиент запросил выполнение действия, которое сервер выполнить не может. 
504 Gateway Time-out    proxy-сервер не получил ответа от веб-сервера

Параметры строки запроса (query string parameters)

Одним из самых распространенных способов настройки запроса GET является передача серверу данных в URLстроки запроса.

Обратите внимание, что GET запрос не имеет тела сообщения. Но, это не означает, что с его помощью мы не можем передать серверу никакую информацию. Это можно делать с помощью специальных GET параметров. Чтобы добавить GET параметры к запросу, нужно в конце URL-адреса поставить знак ? и после него начинать задавать их по следующему правилу: имя_параметра1=значение_параметра1&имя_параметра2=значение_параметра2. Разделителем между параметрами служит знак &.

Для передачи GET параметров запроса необходимо передать нужную информацию в именованный параметр params метода get(). Например, следующим способом вы можете использовать Search API GitHub для более узкого поиска репозитория библиотеки requests:

Переадресация

301 Moved Permanently   Затребованный URI перенесен на новое место (возможно на другой сайт). Новое местонахождение затребованного документа указывается в заголовке Location. 
302 Moved Temporarily   Затребованный URI перемешен, но лишь временно.
304 Not Modified    Проверка ого, что файл не менялся с запрошенной даты (заголовок lf-Modified-Since в запросе).

Передача данных в ответе сервера

Несколько заголовков используемых в ответе сервера, позволяют точно описать формат и размер передаваемых данных.

Content-Type: Тип сообщения, аналогичен типу содержимого в стандарте MIME и указывается в формате тип/подтип.

Серверы используют типы сообщения в заголовках Content-Type, чтобы сообщить клиенту о том, в каком формате передается прилагаемое содержимое

Пример использования get запроса

В примере показана простая HTML форма фильтра по нескольким параметрам.

HTML код формы, генерирующей GET запрос:

Пример использования post запроса

В примере показана простая HTML форма авторизации.

HTML код формы, генерирующей POST запрос:

Производительность

При использовании requests, особенно при работе ваших приложений непосредственно в production environment среде, важно учитывать влияние производительности. Такие возможности приложения, как контроль над времени ожидания ответа сервера, сессиями и ограничение повторных попыток обращения к удаленным службам, помогут обеспечить бесперебойную и устойчивую работу вашего приложения.

Содержимое ответа (content)

Ответ на успешный запрос GET часто содержит в сообщении некоторую ценную информацию, известную так же, как полезное содержимое (payload). Используя атрибуты и методы объекта Response, мы можем просматривать его содержимое в различных форматах.

Чтобы получить содержимое ответа в бинарном виде, мы можем использовать свойство Response.content:

Способы работы с restful api

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

Тайм-ауты timeouts

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

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

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

По умолчанию requests будет ждать ответа на запрос от сервера до бесконечности, поэтому рекомендуется практически во всех случаях указывать интервал ожидания, чтобы избежать всех, перечисленных выше, негативных последствий. Чтобы установить интервал времени ожидания запроса, используйте именованный параметр timeout.

Успешные ответы

200 OK  Запрос клиента обработан успешно, и ответ сервера содержит затребованные данные. 

Заключение

И так мы прошли долгий путь в изучении возможностей Python библиотеки requests.

Теперь вы умеете:

Похожее:  Изменение данных в лицевом счёте

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *