إدخال FastAPI

بدلا من المقدمة

, . , , . . , , . , copy/paste , . , .
 


:

  • ,
  • ,
  • ,

, , HTTP API, POST , , . FastAPI, ?


من هو FastAPI؟


FastAPI هو إطار عمل لإنشاء خوادم HTTP API موجزة وسريعة إلى حد ما مع التحقق من الصحة والتسلسل والمزامنة المضمنة ،
كما يقولون ، خارج الصندوق. وهو يقف على أكتاف الأطر الأخرى اثنين: العمل مع شبكة الإنترنت في FastAPI تشارك Starlette ، ومسؤولة عن التحقق من صحة Pydantic .


تبين أن الحاصدة خفيفة ، وغير محملة وأكثر من كافية في الوظائف.


الحد الأدنى المطلوب


يتطلب FastAPI خادم ASGI للعمل ، بشكل افتراضي تقدم الوثائق uvcorn ، استنادًا إلى uvloop ، ولكن يمكن FastAPI أيضًا العمل مع خوادم أخرى ، على سبيل المثال ، c hypercorn


هنا تبعياتي:


[packages]
fastapi = "*"
uvicorn = "*"

وهذا أكثر من كافي.


للقراء الأكثر شمولاً ، في نهاية المقالة يوجد رابط إلى المستودع مع الروبوت ، حيث يمكنك إلقاء نظرة على تبعيات التطوير والاختبار.

حسنا ، لقد pipenv install -dبدأنا!


بناء API


وتجدر الإشارة إلى أن نهج تصميم المعالجات في FastAPI يشبه إلى حد كبير النهج المتبع في قارورة ، وزجاجة ، وآلاف منهم. من الواضح أن ملايين الذباب لا يمكن أن يكونوا مخطئين.


في التقريب الأول ، بدا مسار معالجة الإصدار الخاص بي كما يلي:


from fastapi import FastAPI
from starlette import status
from starlette.responses import Response

from models import Body

app = FastAPI()  # noqa: pylint=invalid-name

@app.post("/release/")
async def release(*,
                  body: Body,
                  chat_id: str = None):
    await proceed_release(body, chat_id)
    return Response(status_code=status.HTTP_200_OK)

, , , FastAPI Body, chat_id URL params


models.py:


from datetime import datetime
from enum import Enum

from pydantic import BaseModel, HttpUrl

class Author(BaseModel):
    login: str
    avatar_url: HttpUrl

class Release(BaseModel):
    name: str
    draft: bool = False
    tag_name: str
    html_url: HttpUrl
    author: Author
    created_at: datetime
    published_at: datetime = None
    body: str

class Body(BaseModel):
    action: str
    release: Release

, Pydantic. , , , :


class Body(BaseModel):
    action: str
    releases: List[Release]

FastAPI . . , - — .


Pydantic , HttpUrl, URL , FastAPI . Pydantic


.



FastAPI , , , ,
— !


FastAPI , :


from fastapi import FastAPI, HTTPException, Depends
from starlette import status
from starlette.requests import Request

import settings
from router import api_router
from utils import check_auth

docs_kwargs = {}  # noqa: pylint=invalid-name
if settings.ENVIRONMENT == 'production':
    docs_kwargs = dict(docs_url=None, redoc_url=None)  # noqa: pylint=invalid-name

app = FastAPI(**docs_kwargs)  # noqa: pylint=invalid-name

async def check_auth_middleware(request: Request):
    if settings.ENVIRONMENT in ('production', 'test'):
        body = await request.body()
        if not check_auth(body, request.headers.get('X-Hub-Signature', '')):
            raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)

app.include_router(api_router, dependencies=[Depends(check_auth_middleware)])

, request.body — , . FastAPI( Starlette) , .


, FastAPI — OpenAPI Swagger/ReDoc , _/docs _/redoc .


. .


, :


from fastapi import APIRouter
from starlette import status
from starlette.responses import Response

from bot import proceed_release
from models import Body, Actions

api_router = APIRouter()  # noqa: pylint=invalid-name

@api_router.post("/release/")
async def release(*,
                  body: Body,
                  chat_id: str = None,
                  release_only: bool = False):

    if (body.release.draft and not release_only) \
            or body.action == Actions.released:
        res = await proceed_release(body, chat_id)
        return Response(status_code=res.status_code)
    return Response(status_code=status.HTTP_200_OK)


, HTTP API- , .



FastAPI — , , , . , (, , 2020- ?
), .


, , , , , FastAPI.



, , . — , , , , .


, , github actions


انتهى التقرير ، شكرا لكم جميعا!


All Articles