๐ ๐จ - ๐ธ, ๐, ๐, ๐¶
๐ข, FastAPI ๐ ๐จ ๐จ โ๏ธ JSONResponse
.
๐ ๐ช ๐ โซ๏ธ ๐ฌ Response
๐ ๐ ๐จ ๐จ ๐.
โ๏ธ ๐ฅ ๐ ๐จ Response
๐, ๐ ๐ ๐ซ ๐ ๐, & ๐งพ ๐ ๐ซ ๐ ๐ (๐ผ, ๐ ๐ฏ "๐ป ๐", ๐บ๐ธ๐ ๐ Content-Type
๐ ๐ ๐).
โ๏ธ ๐ ๐ช ๐ฃ Response
๐ ๐ ๐ โ๏ธ, โก ๐ ๏ธ ๐จโ๐จ.
๐ ๐ ๐ ๐จ โช๏ธโก๏ธ ๐ โก ๐ ๏ธ ๐ข ๐ ๐ฎ ๐ ๐ Response
.
& ๐ฅ ๐ Response
โ๏ธ ๐ป ๐ป ๐ (application/json
), ๐ ๐ผ โฎ๏ธ JSONResponse
& UJSONResponse
, ๐ฝ ๐ ๐จ ๐ ๐ ๐ (& โฝ) โฎ๏ธ ๐ Pydantic response_model
๐ ๐ ๐ฃ โก ๐ ๏ธ ๐จโ๐จ.
Note
๐ฅ ๐ โ๏ธ ๐จ ๐ โฎ๏ธ ๐ โโ ๐ป ๐, FastAPI ๐ โ ๐ ๐จ โ๏ธ ๐ โโ ๐, โซ๏ธ ๐ ๐ซ ๐ ๐จ ๐ ๐ฎ ๐ ๐ ๐ฉบ.
โ๏ธ ORJSONResponse
¶
๐ผ, ๐ฅ ๐ โ ๐ญ, ๐ ๐ช โ & โ๏ธ orjson
& โ ๐จ ORJSONResponse
.
๐ Response
๐ (๐ง-๐) ๐ ๐ โ๏ธ & ๐ฃ โซ๏ธ โก ๐ ๏ธ ๐จโ๐จ.
โญ ๐จ, ๐จ Response
๐ ๐
โฉ ๐ ๐ฌ ๐.
๐ โฉ๏ธ ๐ข, FastAPI ๐ โ ๐ ๐ฌ ๐ & โ ๐ญ โซ๏ธ ๐ป โฎ๏ธ ๐ป, โ๏ธ ๐ ๐ป ๐ ๐ข ๐ฌ ๐ฐ. ๐ โซ๏ธโ โ ๐ ๐จ โ ๐, ๐ผ ๐ฝ ๐ท.
โ๏ธ ๐ฅ ๐ ๐ฏ ๐ ๐ ๐ ๐ ๐ฌ ๐ป โฎ๏ธ ๐ป, ๐ ๐ช ๐ถโโ๏ธ โซ๏ธ ๐ ๐จ ๐ & โ โ ๐ฅ ๐ FastAPI ๐ โ๏ธ ๐ถโโ๏ธ ๐ ๐จ ๐ ๐ jsonable_encoder
โญ ๐ถโโ๏ธ โซ๏ธ ๐จ ๐.
from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
app = FastAPI()
@app.get("/items/", response_class=ORJSONResponse)
async def read_items():
return ORJSONResponse([{"item_id": "Foo"}])
Info
๐ข response_class
๐ โ๏ธ ๐ฌ "๐ป ๐" ๐จ.
๐ ๐ผ, ๐บ๐ธ๐ ๐ Content-Type
๐ โ application/json
.
& โซ๏ธ ๐ ๐ โ ๐.
Tip
ORJSONResponse
โณ ๐ด ๐ช FastAPI, ๐ซ ๐.
๐ธ ๐จ¶
๐จ ๐จ โฎ๏ธ ๐ธ ๐ โช๏ธโก๏ธ FastAPI, โ๏ธ HTMLResponse
.
- ๐
HTMLResponse
. - ๐ถโโ๏ธ
HTMLResponse
๐ขresponse_class
๐ โก ๐ ๏ธ ๐จโ๐จ.
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get("/items/", response_class=HTMLResponse)
async def read_items():
return """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
Info
๐ข response_class
๐ โ๏ธ ๐ฌ "๐ป ๐" ๐จ.
๐ ๐ผ, ๐บ๐ธ๐ ๐ Content-Type
๐ โ text/html
.
& โซ๏ธ ๐ ๐ โ ๐.
๐จ Response
¶
๐ ๐จ ๐จ ๐, ๐ ๐ช ๐ ๐จ ๐ ๐ โก ๐ ๏ธ, ๐ฌ โซ๏ธ.
๐ ๐ผ โช๏ธโก๏ธ ๐, ๐ฌ HTMLResponse
, ๐ช ๐ ๐:
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
@app.get("/items/")
async def read_items():
html_content = """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)
Warning
Response
๐จ ๐ ๐ โก ๐ ๏ธ ๐ข ๐ ๐ซ ๐ ๐ (๐ผ, Content-Type
๐ ๐ซ ๐) & ๐ ๐ซ โญ ๐ง ๐ ๐ฉบ.
Info
โ๏ธ, โ Content-Type
๐, ๐ ๐, โ๏ธ, ๐ ๐ โช๏ธโก๏ธ Response
๐ ๐ ๐จ.
๐ ๐ & ๐ Response
¶
๐ฅ ๐ ๐ ๐ ๐จ โช๏ธโก๏ธ ๐ ๐ข โ๏ธ ๐ ๐ฐ ๐ "๐ป ๐" ๐, ๐ ๐ช โ๏ธ response_class
๐ข & ๐จ Response
๐.
response_class
๐ โคด๏ธ โ๏ธ ๐ด ๐ ๐ โก ๐ ๏ธ, โ๏ธ ๐ Response
๐ โ๏ธ.
๐จ HTMLResponse
๐¶
๐ผ, โซ๏ธ ๐ช ๐ณ ๐:
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
def generate_html_response():
html_content = """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)
@app.get("/items/", response_class=HTMLResponse)
async def read_items():
return generate_html_response()
๐ ๐ผ, ๐ข generate_html_response()
โช ๐ & ๐จ Response
โฉ๏ธ ๐ฌ ๐ธ str
.
๐ฌ ๐ ๐ค generate_html_response()
, ๐ โช ๐ฌ Response
๐ ๐ ๐ ๐ข FastAPI ๐ญ.
โ๏ธ ๐ ๐ถโโ๏ธ HTMLResponse
response_class
๐โโ๏ธ, FastAPI ๐ ๐ญ โ ๐ โซ๏ธ ๐ & ๐ ๐ฉบ ๐ธ โฎ๏ธ text/html
:
๐ช ๐จ¶
๐ฅ ๐ช ๐จ.
โ๏ธ ๐คฏ ๐ ๐ ๐ช โ๏ธ Response
๐จ ๐ณ ๐, โ๏ธ โ ๐ ๐ง-๐.
๐ก โน
๐ ๐ช โ๏ธ from starlette.responses import HTMLResponse
.
FastAPI ๐ ๐ starlette.responses
fastapi.responses
๐ช ๐, ๐ฉโ๐ป. โ๏ธ ๐
๐ช ๐จ ๐ ๐ โช๏ธโก๏ธ ๐.
Response
¶
๐ Response
๐, ๐ ๐ ๐จ ๐ โช๏ธโก๏ธ โซ๏ธ.
๐ ๐ช ๐จ โซ๏ธ ๐.
โซ๏ธ ๐ซ ๐ ๐ข:
content
-str
โ๏ธbytes
.status_code
-int
๐บ๐ธ๐ ๐ ๐.headers
-dict
๐ป.media_type
-str
๐ค ๐ป ๐. ๐คถ โ."text/html"
.
FastAPI (๐ค ๐) ๐ ๐ ๐ ๐-๐ ๐. โซ๏ธ ๐ ๐ ๐-๐ ๐, โ๏ธ ๐ = & ๐ = โ ๐.
from fastapi import FastAPI, Response
app = FastAPI()
@app.get("/legacy/")
def get_legacy_data():
data = """<?xml version="1.0"?>
<shampoo>
<Header>
Apply shampoo here.
</Header>
<Body>
You'll have to use soap here.
</Body>
</shampoo>
"""
return Response(content=data, media_type="application/xml")
HTMLResponse
¶
โ โ โ๏ธ ๐ข & ๐จ ๐ธ ๐จ, ๐ โ ๐.
PlainTextResponse
¶
โ โ โ๏ธ ๐ข & ๐จ โ โ ๐จ.
from fastapi import FastAPI
from fastapi.responses import PlainTextResponse
app = FastAPI()
@app.get("/", response_class=PlainTextResponse)
async def main():
return "Hello World"
JSONResponse
¶
โ ๐ฝ & ๐จ application/json
๐ ๐จ.
๐ ๐ข ๐จ โ๏ธ FastAPI, ๐ โ ๐.
ORJSONResponse
¶
โฉ ๐ ๐ป ๐จ โ๏ธ orjson
, ๐ โ ๐.
UJSONResponse
¶
๐ ๐ป ๐จ โ๏ธ ujson
.
Warning
ujson
๐ ๐ ๐ ๐ ๐-๐ ๏ธ โ โซ๏ธ ๐ต ๐-๐ผ.
from fastapi import FastAPI
from fastapi.responses import UJSONResponse
app = FastAPI()
@app.get("/items/", response_class=UJSONResponse)
async def read_items():
return [{"item_id": "Foo"}]
Tip
โซ๏ธ ๐ช ๐ ORJSONResponse
๐ช โฉ ๐.
RedirectResponse
¶
๐จ ๐บ๐ธ๐ โ. โ๏ธ 3๏ธโฃ0๏ธโฃ7๏ธโฃ ๐ ๐ (๐ โ) ๐ข.
๐ ๐ช ๐จ RedirectResponse
๐:
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/typer")
async def redirect_typer():
return RedirectResponse("https://typer.tiangolo.com")
โ๏ธ ๐ ๐ช โ๏ธ โซ๏ธ response_class
๐ข:
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/fastapi", response_class=RedirectResponse)
async def redirect_fastapi():
return "https://fastapi.tiangolo.com"
๐ฅ ๐ ๐, โคด๏ธ ๐ ๐ช ๐จ ๐ ๐ โช๏ธโก๏ธ ๐ โก ๐ ๏ธ ๐ข.
๐ ๐ผ, status_code
โ๏ธ ๐ ๐ข 1๏ธโฃ RedirectResponse
, โ 307
.
๐ ๐ช โ๏ธ status_code
๐ข ๐ โฎ๏ธ response_class
๐ข:
from fastapi import FastAPI
from fastapi.responses import RedirectResponse
app = FastAPI()
@app.get("/pydantic", response_class=RedirectResponse, status_code=302)
async def redirect_pydantic():
return "https://pydantic-docs.helpmanual.io/"
StreamingResponse
¶
โ ๐ ๐ โ๏ธ ๐ ๐/๐ป & ๐ ๐จ ๐ช.
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
async def fake_video_streamer():
for i in range(10):
yield b"some fake video bytes"
@app.get("/")
async def main():
return StreamingResponse(fake_video_streamer())
โ๏ธ StreamingResponse
โฎ๏ธ ๐-๐ ๐¶
๐ฅ ๐ โ๏ธ ๐-๐ ๐ (โ
๐ ๐จ open()
), ๐ ๐ช โ ๐ ๐ข ๐ ๐คญ ๐ ๐-๐ ๐.
๐ ๐, ๐ ๐ซ โ๏ธ โ โซ๏ธ ๐ ๐ฅ ๐พ, & ๐ ๐ช ๐ถโโ๏ธ ๐ ๐ ๐ข StreamingResponse
, & ๐จ โซ๏ธ.
๐ ๐ ๐ ๐ ๐ โฎ๏ธ โ ๐พ, ๐น ๐ญ, & ๐.
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
some_file_path = "large-video-file.mp4"
app = FastAPI()
@app.get("/")
def main():
def iterfile(): # (1)
with open(some_file_path, mode="rb") as file_like: # (2)
yield from file_like # (3)
return StreamingResponse(iterfile(), media_type="video/mp4")
1๏ธโฃ. ๐ ๐ ๐ข. โซ๏ธ "๐ ๐ข" โฉ๏ธ โซ๏ธ ๐ yield
๐ ๐.
2๏ธโฃ. โ๏ธ with
๐ซ, ๐ฅ โ ๐ญ ๐ ๐-๐ ๐ ๐ช โฎ๏ธ ๐ ๐ข ๐จ. , โฎ๏ธ โซ๏ธ ๐ ๐จ ๐จ.
3๏ธโฃ. ๐ yield from
๐ฌ ๐ข ๐ ๐คญ ๐ ๐ ๐ file_like
. & โคด๏ธ, ๐ ๐ ๐, ๐พ ๐ ๐ ๐ โช๏ธโก๏ธ ๐ ๐ ๐ข.
, โซ๏ธ ๐ ๐ข ๐ ๐จ "๐ญ" ๐ท ๐ณ ๐ ๐.
๐จ โซ๏ธ ๐ ๐, ๐ฅ ๐ช ๐ฎ โซ๏ธ `with` ๐ซ, & ๐ ๐, ๐ ๐ โซ๏ธ ๐ช โฎ๏ธ ๐.
Tip
๐ ๐ ๐ฅ ๐ฅ โ๏ธ ๐ฉ open()
๐ ๐ซ ๐โ๐ฆบ async
& await
, ๐ฅ ๐ฃ โก ๐ ๏ธ โฎ๏ธ ๐ def
.
FileResponse
¶
๐ ๐ ๐ ๐จ.
โ ๐ โ โ ๐ ๐ ๐ ๐จ ๐:
path
- ๐ ๐ ๐.headers
- ๐ ๐ ๐ ๐, ๐.media_type
- ๐ป ๐ค ๐ป ๐. ๐ฅ ๐ข, ๐ โ๏ธ โก ๐ โ๏ธ ๐ ๐ป ๐.filename
- ๐ฅ โ, ๐ ๐ ๐ ๐จContent-Disposition
.
๐ ๐จ ๐ ๐ โ Content-Length
, Last-Modified
& ETag
๐.
from fastapi import FastAPI
from fastapi.responses import FileResponse
some_file_path = "large-video-file.mp4"
app = FastAPI()
@app.get("/")
async def main():
return FileResponse(some_file_path)
๐ ๐ช โ๏ธ response_class
๐ข:
from fastapi import FastAPI
from fastapi.responses import FileResponse
some_file_path = "large-video-file.mp4"
app = FastAPI()
@app.get("/", response_class=FileResponse)
async def main():
return some_file_path
๐ ๐ผ, ๐ ๐ช ๐จ ๐ โก ๐ โช๏ธโก๏ธ ๐ โก ๐ ๏ธ ๐ข.
๐ ๐จ ๐¶
๐ ๐ช โ ๐ ๐ ๐ ๐จ ๐, ๐ โช๏ธโก๏ธ Response
& โ๏ธ โซ๏ธ.
๐ผ, โก๏ธ ๐ฌ ๐ ๐ ๐ โ๏ธ orjson
, โ๏ธ โฎ๏ธ ๐ โ ๐ซ โ๏ธ ๐ ORJSONResponse
๐.
โก๏ธ ๐ฌ ๐ ๐ โซ๏ธ ๐จ ๐ & ๐ ๐ป, ๐ ๐ โ๏ธ Orjson ๐ orjson.OPT_INDENT_2
.
๐ ๐ช โ CustomORJSONResponse
. ๐ ๐ ๐ โ๏ธ โ Response.render(content)
๐ฉโ๐ฌ ๐ ๐จ ๐ bytes
:
from typing import Any
import orjson
from fastapi import FastAPI, Response
app = FastAPI()
class CustomORJSONResponse(Response):
media_type = "application/json"
def render(self, content: Any) -> bytes:
assert orjson is not None, "orjson must be installed"
return orjson.dumps(content, option=orjson.OPT_INDENT_2)
@app.get("/", response_class=CustomORJSONResponse)
async def main():
return {"message": "Hello World"}
๐ โฉ๏ธ ๐ฌ:
{"message": "Hello World"}
...๐ ๐จ ๐ ๐จ:
{
"message": "Hello World"
}
โ๏ธ, ๐ ๐ ๐ฒ ๐ ๐ ๐ ๐ โ ๐ ๐ ๐ โ ๐ป. ๐ถ
๐ข ๐จ ๐¶
๐โ ๐ FastAPI ๐ ๐ โ๏ธ APIRouter
๐ ๐ช โ โ ๐จ ๐ โ๏ธ ๐ข.
๐ข ๐ ๐ฌ ๐ default_response_class
.
๐ผ ๐, FastAPI ๐ โ๏ธ ORJSONResponse
๐ข, ๐ โก ๐ ๏ธ, โฉ๏ธ JSONResponse
.
from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
app = FastAPI(default_response_class=ORJSONResponse)
@app.get("/items/")
async def read_items():
return [{"item_id": "Foo"}]
Tip
๐ ๐ช ๐ response_class
โก ๐ ๏ธ โญ.
๐ ๐งพ¶
๐ ๐ช ๐ฃ ๐ป ๐ & ๐ ๐ โน ๐ โ๏ธ responses
: ๐ ๐จ ๐.