2023年8月2日水曜日

fastapi で XML なレスポンスを考える (カスタムレスポンス編)

fastapi で XML なレスポンスを考える (カスタムレスポンス編)

概要

前回 pydantic-xml を使ってレスポンスの構造を XML で表現してみました

今回は Response ではなく独自で定義した Response クラスを使ってレスポンスを生成してみたいと思います

環境

  • Python 3.11.3
  • fastapi 0.100.1
  • pydantic-xml 1.0.0

サンプルコード

  • vim ./app.py
from typing import Optional, Union

from fastapi import FastAPI, Response
from pydantic_xml import BaseXmlModel, element
from starlette.background import BackgroundTask

app = FastAPI()


class User(BaseXmlModel, tag="User"):
    name: str = element(tag="Name")
    age: int = element(tag="Age")


class XmlResponse(Response):
    def __init__(
        self,
        content: Union[str, bytes],
        status_code: int = 200,
        background: Optional[BackgroundTask] = None,
    ):
        super().__init__(
            content,
            status_code=status_code,
            media_type="application/xml",
            background=background,
        )


@app.get("/", response_class=XmlResponse, response_model=User)
def xml():
    user = User(name="hawksnowlog", age=10)
    return XmlResponse(content=user.to_xml())

動作確認

  • pipenv run uvicorn app:app --reload
  • curl -v localhost:8000/

=> <User><Name>hawksnowlog</Name><Age>10</Age></User>

解説

Response を継承した XmlResponse を定義しています
XmlResponse は response_class に指定できます
また response_model に User も指定できます

json を返却したい場合には以下のように response_class の指定を外せば OK です

@app.get("/", response_model=User)
def xml():
    user = User(name="hawksnowlog", age=10)
    return user

最後に

カスタム Response を使って XML レスポンスを返却する方法を紹介しました
ただこの方法でも openapi に載らないので結局 responses 属性を指定することになります

XmlResponse を使った場合に openapi にレスポンス情報を掲載するにはどうすればいいだろうか

0 件のコメント:

コメントを投稿