Перейти к основному содержимому

FastAPI в Serverless-функции

· 3 мин. чтения

У меня уже есть пост про то как запустить FastAPI в Serverless контейнере на Yandex Cloud, а также пост как в функции запустить популярные JS фреймворки. Пришло время взять понемногу из этих постов и запустить FastAPI в Serverless функции. Для этого нам понадобится python библиотека Mangum. Она не сказать что очень активно поддерживается. Это заметно и по истории коммитов и по тому что они упустили домен, где была документация и теперь там лежит рекламный блог. Недавно разработку подхватил другой разработчик. Восстановил документацию и это дает надежду на то что проект будет развиваться дальше.

Установка

pip install mangum

Также не забудьте добавить FastAPI и Mangum в ваш requirements.txt.

requirements.txt
fastapi
mangum

Пример

from mangum import Mangum
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
def read_root():
return {"Hello": "World"}


@app.get("/items/{item_id}")
def read_item(item_id: int, q: str = None):
return {"item_id": item_id, "q": q}


handler = Mangum(app)

В принципе это почти всё, что нужно. Единственное, что нужно сделать, чтобы этот пример заработал в Yandex Cloud это поставить нашу функцию за API Gateway. Это нужно потому что адаптер Mangum ожидает на вход event в формате AWS. В Yandex Cloud это будет выглядеть так:

openapi.yaml
openapi: 3.0.0
info:
title: Sample API
version: 1.0.0
paths:
/:
x-yc-apigateway-any-method:
x-yc-apigateway-integration:
payload_format_version: '1.0'
function_id: d4e**************
tag: $latest
type: cloud_functions

Обратите внимание на строчку 9 payload_format_version: '1.0'. Это нужно для того, чтобы указать API Gateway, что функцию нужно вызывать с событием в формате AWS. Пример события:

{
"version": <версия формата запроса>,
"resource": <ресурс, соответствующий запросу в спецификации>,
"path": <фактический путь запроса>,
"httpMethod": <название HTTP-метода>,
"headers": <словарь со строковыми значениями HTTP-заголовков>,
"multiValueHeaders": <словарь со списками значений HTTP-заголовков>,
"queryStringParameters": <словарь queryString-параметров>,
"multiValueQueryStringParameters": <словарь списков значений queryString-параметров>,
"requestContext": <словарь с контекстом запроса>,
"pathParameters": <словарь значений параметров пути запроса>,
"body": <содержимое запроса>,
"isBase64Encoded": <true или false>,
// дополнительные поля:
"parameters": <словарь значений параметров запроса, описанных в спецификации OpenAPI>,
"multiValueParameters": <словарь со списками значений параметров запроса, описанных в спецификации OpenAPI>,
"operationId": <operationId, соответствующий запросу в спецификации OpenAPI>
}

Если этого не сделать, то в параметр path будет передан не фактический путь запроса, а путь из спецификации. Например:

paths:
/{files+}:
get:
...

Для такой спецификации в параметр path будет передано /{files+} вместо фактического пути запроса. Поэтому очень важно указать payload_format_version: '1.0', совместимый с AWS.

Жадные параметры

Если вы не хотите описывать все пути в спецификации, то можно использовать жадные параметры. Например:

openapi.yaml
openapi: 3.0.0
info:
title: Sample API
version: 1.0.0
paths:
/{proxy+}:
x-yc-apigateway-any-method:
parameters:
- name: proxy
in: path
required: true
schema:
type: string
x-yc-apigateway-integration:
payload_format_version: '1.0'
function_id: d4e**************
tag: $latest
type: cloud_functions

Заключение

Mangum позволяет запустить FastAPI в Serverless функции. Для его корректной работы в Yandex Cloud нужен правивильно настроенный API Gateway. В принципе это всё, что нужно для того, чтобы запустить FastAPI в Serverless функции.