Files
docs-fastapi/docs/uk/docs/advanced/openapi-callbacks.md
T

187 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Зворотні виклики OpenAPI { #openapi-callbacks }
Ви можете створити API з *операцією шляху*, яка ініціюватиме запит до *зовнішнього API*, створеного кимось іншим (ймовірно тим самим розробником, який буде *використовувати* ваш API).
Процес, що відбувається, коли ваш застосунок API викликає *зовнішній API*, називається «зворотний виклик». Тому що програмне забезпечення, написане зовнішнім розробником, надсилає запит до вашого API, а потім ваш API *виконує зворотний виклик*, надсилаючи запит до *зовнішнього API* (його, ймовірно, також створив той самий розробник).
У такому випадку вам може знадобитися задокументувати, яким має бути той *зовнішній API*: яку *операцію шляху* він має мати, яке тіло очікувати, яку відповідь повертати тощо.
## Застосунок зі зворотними викликами { #an-app-with-callbacks }
Розгляньмо це на прикладі.
Уявімо, що ви розробляєте застосунок для створення рахунків.
Ці рахунки матимуть `id`, `title` (необов'язково), `customer` і `total`.
Користувач вашого API (зовнішній розробник) створить рахунок у вашому API за допомогою POST-запиту.
Потім ваш API буде (уявімо):
- Надсилати рахунок деякому клієнту зовнішнього розробника.
- Отримувати оплату.
- Надсилати сповіщення назад користувачу API (зовнішньому розробнику).
- Це буде зроблено шляхом надсилання POST-запиту (з *вашого API*) до деякого *зовнішнього API*, наданого тим зовнішнім розробником (це і є «зворотний виклик»).
## Звичайний застосунок **FastAPI** { #the-normal-fastapi-app }
Спочатку подивімося, як виглядав би звичайний застосунок API до додавання зворотного виклику.
Він матиме *операцію шляху*, яка отримуватиме тіло `Invoice`, і параметр запиту `callback_url`, що міститиме URL для зворотного виклику.
Ця частина цілком звична, більшість коду вам, ймовірно, уже знайома:
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[7:11,34:51] *}
/// tip | Порада
Параметр запиту `callback_url` використовує тип Pydantic [Url](https://docs.pydantic.dev/latest/api/networks/).
///
Єдина нова річ - це `callbacks=invoices_callback_router.routes` як аргумент *декоратора операції шляху*. Далі розглянемо, що це таке.
## Документування зворотного виклику { #documenting-the-callback }
Фактичний код зворотного виклику сильно залежатиме від вашого застосунку API.
І, ймовірно, сильно відрізнятиметься від застосунку до застосунку.
Це можуть бути лише один-два рядки коду, наприклад:
```Python
callback_url = "https://example.com/api/v1/invoices/events/"
httpx.post(callback_url, json={"description": "Invoice paid", "paid": True})
```
Але, можливо, найважливіша частина зворотного виклику - переконатися, що користувач вашого API (зовнішній розробник) правильно реалізує *зовнішній API* відповідно до даних, які *ваш API* надсилатиме в тілі запиту зворотного виклику тощо.
Тому далі ми додамо код, щоб задокументувати, яким має бути цей *зовнішній API*, щоб приймати зворотний виклик від *вашого API*.
Ця документація з'явиться в Swagger UI за адресою `/docs` у вашому API і дасть змогу зовнішнім розробникам зрозуміти, як створити *зовнішній API*.
У цьому прикладі сам зворотний виклик не реалізовано (це може бути лише один рядок коду), лише частину з документацією.
/// tip | Порада
Фактичний зворотний виклик - це просто HTTP-запит.
Реалізуючи зворотний виклик самостійно, ви можете скористатися, наприклад, [HTTPX](https://www.python-httpx.org) або [Requests](https://requests.readthedocs.io/).
///
## Напишіть код документації для зворотного виклику { #write-the-callback-documentation-code }
Цей код не виконуватиметься у вашому застосунку, він потрібен лише, щоб *задокументувати*, яким має бути *зовнішній API*.
Але ви вже знаєте, як легко створювати автоматичну документацію для API за допомогою **FastAPI**.
Тож ми скористаємося цими знаннями, щоб задокументувати, яким має бути *зовнішній API*... створивши *операції шляху*, які має реалізувати зовнішній API (ті, які викликатиме ваш API).
/// tip | Порада
Пишучи код для документування зворотного виклику, корисно уявити, що ви - той *зовнішній розробник*. І що ви зараз реалізуєте *зовнішній API*, а не *ваш API*.
Тимчасово прийнявши цю точку зору (*зовнішнього розробника*), вам буде очевидніше, куди помістити параметри, яку Pydantic-модель використати для тіла, для відповіді тощо для того *зовнішнього API*.
///
### Створіть `APIRouter` зворотного виклику { #create-a-callback-apirouter }
Спочатку створіть новий `APIRouter`, який міститиме один або кілька зворотних викликів.
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[1,23] *}
### Створіть *операцію шляху* зворотного виклику { #create-the-callback-path-operation }
Щоб створити *операцію шляху* зворотного виклику, використайте той самий `APIRouter`, який ви створили вище.
Вона має виглядати як звичайна *операція шляху* FastAPI:
- Ймовірно має містити оголошення тіла, яке вона приймає, наприклад `body: InvoiceEvent`.
- І також може містити оголошення відповіді, яку вона повертає, наприклад `response_model=InvoiceEventReceived`.
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[14:16,19:20,26:30] *}
Є 2 основні відмінності від звичайної *операції шляху*:
- Їй не потрібен реальний код, адже ваш застосунок ніколи не викликатиме цей код. Вона використовується лише для документування *зовнішнього API*. Тому функція може просто містити `pass`.
- *Шлях* може містити [вираз OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression) (див. нижче), де можна використовувати змінні з параметрами та частини оригінального запиту, надісланого до *вашого API*.
### Вираз шляху зворотного виклику { #the-callback-path-expression }
*Шлях* зворотного виклику може містити [вираз OpenAPI 3](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.1.0.md#key-expression), який включає частини оригінального запиту, надісланого до *вашого API*.
У цьому випадку це `str`:
```Python
"{$callback_url}/invoices/{$request.body.id}"
```
Отже, якщо користувач вашого API (зовнішній розробник) надішле запит до *вашого API* на:
```
https://yourapi.com/invoices/?callback_url=https://www.external.org/events
```
з JSON-тілом:
```JSON
{
"id": "2expen51ve",
"customer": "Mr. Richie Rich",
"total": "9999"
}
```
тоді *ваш API* опрацює рахунок і згодом надішле запит зворотного виклику на `callback_url` (*зовнішній API*):
```
https://www.external.org/events/invoices/2expen51ve
```
з JSON-тілом на кшталт:
```JSON
{
"description": "Payment celebration",
"paid": true
}
```
і очікуватиме відповідь від того *зовнішнього API* з JSON-тілом на кшталт:
```JSON
{
"ok": true
}
```
/// tip | Порада
Зверніть увагу, що використаний URL зворотного виклику містить URL, отриманий як параметр запиту в `callback_url` (`https://www.external.org/events`), а також `id` рахунку зсередини JSON-тіла (`2expen51ve`).
///
### Додайте маршрутизатор зворотного виклику { #add-the-callback-router }
На цьому етапі ви маєте потрібні *операції шляху зворотного виклику* (ті, які має реалізувати *зовнішній розробник* у *зовнішньому API*) у створеному вище маршрутизаторі зворотного виклику.
Тепер використайте параметр `callbacks` у *декораторі операції шляху вашого API*, щоб передати атрибут `.routes` з цього маршрутизатора зворотного виклику:
{* ../../docs_src/openapi_callbacks/tutorial001_py310.py hl[33] *}
/// tip | Порада
Зверніть увагу, що ви передаєте не сам маршрутизатор (`invoices_callback_router`) у `callbacks=`, а його `.routes`, тобто `invoices_callback_router.routes`. FastAPI використає ці маршрути, щоб згенерувати документацію OpenAPI для зворотних викликів.
///
### Перевірте документацію { #check-the-docs }
Тепер ви можете запустити застосунок і перейти за адресою [http://127.0.0.1:8000/docs](http://127.0.0.1:8000/docs).
Ви побачите вашу документацію з розділом «Callbacks» для вашої *операції шляху*, який показує, як має виглядати *зовнішній API*:
<img src="/img/tutorial/openapi-callbacks/image01.png">