Сегодня рассмотрим, что такое Swagger. А, чтобы понять, как работает этот инструмент тестирования и документирования REST API, разберем практический пример, собственноручно написав простенькое Python-приложение с FastAPI в интерактивной среде Google Colab и развернув его через ngrok – утилиту туннелирования локального сервера разработки в общедоступный URL.
Что такое Swagger и при чем здесь REST API
Обычно при тестировании RESTful API, а также при проектировании интеграции веб-приложений аналитик использует фреймворк Swagger от компании SmartBear, который позволяет интерактивно просматривать спецификацию и отправлять запросы. Он включает несколько компонентов, которые могут генерировать документацию на основе существующего кода на основе Java Annotation и создавать клиентов для нее. В визуальном веб-GUI Swagger можно просмотреть типы поддерживаемых HTTP-методов и описание схемы используемых данных, а также протестировать их. Также есть редактор, чтобы специфицировать REST API, т.е. получить документацию OpenAPI версии 3 в YAML или JSON форматах.
Чтобы аналитик или технический писатель мог получить доступ к веб-GUI Swagger тестируемого веб-приложения с REST API, разработчик должен развернуть его, используя SwaggerHub. Эта многопользовательская платформа позволяет определять REST API через спецификацию OpenAPI 3 и управлять ими. Далее рассмотрим, как это делается.
Основы архитектуры и интеграции информационных систем
Код курса
OAIS
Ближайшая дата курса
20 января, 2025
Продолжительность
16 ак.часов
Стоимость обучения
36 000 руб.
Пишем свое RESTful Python-приложение с FastAPI
В качестве примера напишем небольшое RESTful Python-приложение с помощью фреймворка FastAPI в интерактивной среде Google Colab, которое будет поддерживать GET- и POST-запросы для сервиса клиентских заявок. Для простоты возьмем следующую структуру данных по клиентским заявкам, определив ее в JSON-формате:
{ "apps": [ { "course": "TTIS", "name": "Анна", "email": "anna@email.ru", "phone": "123456789" }, { "course": "MODP", "name": "Борис", "email": "boris@email.ru" } ] }
Конвертируем это JSON-сообщение в YAML-формат с помощью онлайн-конвертера https://www.json2yaml.com/, чтобы далее сгенерировать классы для нашего Python-приложения. Конвертация JSON-сообщения дает следующий YAML-документ:
--- apps: - course: TTIS name: Анна email: anna@email.ru phone: '123456789' - course: MODP name: Борис email: boris@email.ru
Используя полученный YAML, cгенерируем классы Python с помощью https://jsonformatter.org/yaml-to-python, чтобы не писать это самостоятельно:
from typing import Optional, List class App: course: str name: str email: str phone: Optional[int] def __init__(self, course: str, name: str, email: str, phone: Optional[int]) -> None: self.course = course self.name = name self.email = email self.phone = phone class Welcome6: apps: List[App] def __init__(self, apps: List[App]) -> None: self.apps = apps
Вставим полученные классы в код Python-скрипта с объявлением HTTP-методов для работы с веб-приложением. Чтобы упростить себе процесс разработки кода, буду использовать веб-фреймворк FastAPI на основе Python 3.6+. Он позволяет быстро написать RESTful веб-приложение, используя стандартную аннотацию типов Python, а также, что наиболее важно в контексте Swagger, поддерживает автоматическую интерактивную документацию на основе открытых стандартов OpenAPI 3 и JSON Schema.
Дополним сгенерированные классы описанием функций, реализующих GET- и POST-запросы к объявленной структуре данных (@app.get() и @app.post() соответственно):
from typing import Union from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() from typing import Optional, List class App(BaseModel): id: int course: str name: str email: Optional[str] phone: Optional[str] class Welcome: apps: List[App] def __init__(self, apps: List[App]) -> None: self.apps = apps @app.get("/") def read_root(): return {"Привет, это мое REST API приложение"} @app.get("/apps/{app_id}") def read_app(app_id: int, q: Union[str, None] = None): return {"app_id": app_id, "q": q} @app.post("/apps/") def add_app(app: App): return {"app_id": app.id, "app_course": app.course, "client_name": app.name, "client_email": app.email, "client_phone": app.phone}
Реализация в Google Colab: веб-сервер unicorn с туннелем через ngrok
В качестве средства проверки гипотез и быстрого прототипирования приложений возьмем интерактивную среду Google Colab, чтобы запустить вышеприведенный скрипт своего Python-приложения. Справедливости ради, стоит отметить, что этот скрипт лишь имитирует сервис работы с клиентскими заявками, поскольку мне было уже лениво разворачивать базу данных и прописывать инструкции подключения к ней. Впрочем, при желании все это тоже можно сделать в Google Colab, используя встроенную в Python легковесную реляционную СУБД SQLlite.
Возвращаясь к моему Pуthon-приложению, запущенному в Google Colab, чтобы получить доступ к нему и просмотреть сгенерированную фреймворком Fast API, документацию, нужно использовать какой-то веб-сервер, домен, хостинг и пр. Напомню, веб-сервер позволяет обращаться к серверному веб-приложению по протоколам HTTP и HTTPS, поддерживая HTTP-стандарты. Настройка всех этих ресурсов точно выходит за рамки компетенций аналитика и займет много времени. Поэтому я решила воспользоваться утилитой ngrok, которая позволяет поделиться локальным сервером разработки localhost, создав безопасный туннель с внешнего URL-адреса на локальный компьютер.
Утилита ngrok запускает на локальном компьютере небольшой клиентский процесс, который создает частный туннель подключения к облачной службе ngrok. Локальный сервер разработки localhost сопоставляется с поддоменом ngrok.io, к которому может получить доступ удаленный пользователь. При этом не нужно открывать порты, настраивать пересылки и выполнять прочие действия системного администратора.
Чтобы воспользоваться возможностями FastAPI и uvicorn – удаленного веб-сервера для Python, в блокноте Google Colab, сперва следует установить их:
# Install requirements !pip install fastapi==0.68.1 !pip install uvicorn==0.15.0
Затем следует установить пакет асинхронных вызовов:
!pip install nest-asyncio
Далее необходимо установить утилиту ngrok:
!pip install pyngrok
Потом идет ячейка с кодом моего Python-приложения:
from typing import Union from fastapi import FastAPI from pydantic import BaseModel app = FastAPI() from typing import Optional, List class App(BaseModel): id: int course: str name: str email: Optional[str] phone: Optional[str] class Welcome: apps: List[App] def __init__(self, apps: List[App]) -> None: self.apps = apps @app.get("/") def read_root(): return {"Привет, это мое REST API приложение"} @app.get("/apps/{app_id}") def read_app(app_id: int, q: Union[str, None] = None): return {"app_id": app_id, "q": q} @app.post("/apps/") def add_app(app: App): return {"app_id": app.id, "app_course": app.course, "client_name": app.name, "client_email": app.email, "client_phone": app.phone}
Пробрасываем туннель для доступа к локальному серверу разработки из внешнего URL, сгенерированного утилитой ngrok. При этом сперва следует получить персональный токен разработчика на сайте этой платформы (https://dashboard.ngrok.com/signup), чтобы вставить его в код:
from pyngrok import ngrok auth_token = "персональный токен разработчика" #@param {type:"string"} # Since we can't access Colab notebooks IP directly we'll use # ngrok to create a public URL for the server via a tunnel # Authenticate ngrok # https://dashboard.ngrok.com/signup # Then go to the "Your Authtoken" tab in the sidebar and copy the API key import os os.system(f"ngrok authtoken {auth_token}")
Создаем сам туннель, чтобы получить публичный URL:
from pyngrok import ngrok # Create tunnel public_url = ngrok.connect(8000, port='8000', bind_tls=True)
И, наконец, запускаем свое Python-приложение с веб-сервером uvicorn:
import nest_asyncio # Allow for asyncio to work within the Jupyter notebook cell nest_asyncio.apply() import uvicorn # Run the FastAPI app using uvicorn print(public_url) uvicorn.run(app)
В заключение в отдельной ячейке пропишем закрытие проброшенного туннеля:
# Kill tunnel ngrok.disconnect(public_url=public_url)
Чтобы обойти ограничения AVG-антивируса моего компьютера, который не позволяет выполнять небезопасные подключения, я добавила в исключения два URL-адреса: https://cdn.ngrok.com/* и внешний URL,сгенерированный утилитой ngrok для туннелирования моего локального сервера разработки locallhost:
Поскольку FastAPI автоматически генерирует документацию, посмотрим на нее, обратившись к конечной точке /docs полученного URL. Видим привычный Swagger UI, где можно протестировать HTTP-методы своего REST API и модель данных.
Протестируем функцию добавления клиентской заявки через POST-запрос:
Чтобы добавить эту спецификацию API в SwaggerHub, получим ее в виде JSON-документа, обратившись к конечной точке /openapi.json полученного URL.
Скопировав содержимое этого JSON-документа, вставим его в SwaggerHub, где он автоматически конвертируется в YAML-формат. При этом вручную добавим раздел с объявлением серверов, чтобы указать URL-адрес uvicorn–сервера, туннелированного с помощью ngrok (выделено жирным):
openapi: 3.0.2 info: title: FastAPI version: 1.0.0 servers: # Added by API Auto Mocking Plugin - description: SwaggerHub API Auto Mocking url: https://virtserver.swaggerhub.com/VICHIGOVAANNA/FastAPI/1.0.0 - url: https://4b53-35-239-255-207.ngrok.io/ description: Production server paths: /: get: summary: Read Root operationId: read_root__get responses: '200': description: Successful Response content: application/json: schema: {} /apps/{app_id}: get: summary: Read App operationId: read_app_apps__app_id__get parameters: - required: true schema: title: App Id type: integer name: app_id in: path - required: false schema: title: Q type: string name: q in: query responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' /apps/: post: summary: Add App operationId: add_app_apps__post requestBody: content: application/json: schema: $ref: '#/components/schemas/App' required: true responses: '200': description: Successful Response content: application/json: schema: {} '422': description: Validation Error content: application/json: schema: $ref: '#/components/schemas/HTTPValidationError' components: schemas: App: title: App required: - id - course - name type: object properties: id: title: Id type: integer course: title: Course type: string name: title: Name type: string email: title: Email type: string phone: title: Phone type: string HTTPValidationError: title: HTTPValidationError type: object properties: detail: title: Detail type: array items: $ref: '#/components/schemas/ValidationError' ValidationError: title: ValidationError required: - loc - msg - type type: object properties: loc: title: Location type: array items: type: string msg: title: Message type: string type: title: Error Type type: string
Встроенный редактор SwaggerHub проверил валидность созданной YAML-спецификации и также предоставляет GUI для тестирования HTTP-методов, объявленных в приложении.
Надеюсь, что это небольшое руководство поможет аналитикам, которые только начинают знакомиться с REST API и Swagger, лучше понять их устройство и принципы работы. Как написать спецификацию OpenAPI вручную, а не получить из исходного кода, я показываю здесь. Про то, какие ошибки чаще всего встречаются при разработке спецификации OpenAPI и как их избежать, вы узнаете в этом материале. А о том, что еще можно написать и запустить в Google Colab, читайте в новой статье про RabbitMQ.
Основы архитектуры и интеграции информационных систем
Код курса
OAIS
Ближайшая дата курса
20 января, 2025
Продолжительность
16 ак.часов
Стоимость обучения
36 000 руб.
А подробнее познакомиться со всеми рассмотренными темами, а также другими основами архитектуры и интеграции информационных систем вам помогут курсы Школы прикладного бизнес-анализа в нашем лицензированном учебном центре обучения и повышения квалификации системных и бизнес-аналитиков в Москве: