3. Custom Response - HTML, Stream, File, others
1. Custom Response - HTML, Stream, File, others
- 기본적으로 FastAPIsms
JSONResponse
를 사용하여 response를 반환한다. - 직접
Response
반환에 표시된 대로Response
를 직접 반환하여 이를 오버라이드할 수 있다. - 그러나
Response
를 직접 반환하면, 데이터가 자동으로 변환되지 않으며 문서가 자동으로 생성되지 않는다. - 하지만 path operation 데코레이터에 사용하려는
Response
를 선언할 수 있는데, path operation function에서 반환하는 내용은 해당Response
내부에 들어간다. - 그리고
JSONResponse
및UJSONResponse
와 같이 해당Response
에 JSON 미디어 타입(application/json
)이 있는 경우, 반환되는 데이터는 path operation 데코레이터에서 선언한 Pydanticresponse_model
로 자동 변환된다.
2. Use ORJSONResponse
- 만약 성능에 초점을 두고 있다면
orjson
을 설치하여 사용하고, response를ORJSONResponse
로 설정할 수 있다.
- 다음과 같이 사용하려는
Response
클래스를 가져와서 path operation 데코레이터에 선언한다.
from fastapi import FastAPI
from fastapi.responses import ORJSONResponse
app = FastAPI()
@app.get("/items/", response_class=ORJSONResponse)
async def resd_items():
return [{"item_id": "Foo"}]
3. HTML Reseponse
- FastAPI에서 HTML response를 반환하려면, 다음과 같이
HTMLResponse
를 사용한다.
1] HTMLResponse
를 임포트한다.
2] path operation 데코레이터의 매개변수 response_class
로 HTMLResponse
를 전달한다.
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>
"""
1) Return a Response
- path operation에서 reponse를 반환하는 것으로 직접 오버라이드할 수 있다.
- 다음과 같이
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)
2) Document in OpenAPI and override Response
- 함수 내부에서 응답을 재정의하지만 동시에 OpenAPI에서 "media type"을 문서화하려는 경우, 매개변수
response_class
를 사용하고Response
객체를 반환할 수 있다. response_class
는 OpenAPI path operation을 문서화하는 데만 사용되지만Response
는 있는 그대로 사용된다.
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()
는 HTML을 반환하는 대신Response
를 생성하고 반환한다. response_class
에서도HTMLResponse
를 전달했기 때문에 FastAPI는 OpenAPI에서 문서화하는 방법을 알게 된다.
4. Available responses
1) Response
- 기본
Response
클래스이며, 다른 모든 responses는 이 클래스에서 상속된다. - 다음과 같은 매개변수를 허용한다.
1] content
str
타입 또는bytes
타입
2] status_code
int
타입으로 HTTP 상태 코드이다.
3] headers
- 문자열
dict
타입
4] media_type
- media type을 제공하는
str
타입
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")
2) HTMLResponse
- 일부 텍스트 또는 bytes를 가져와 HTML response를 반환한다.
3) PlainTextResponse
- 일부 텍스트 또는 bytes를 가져와 일반 텍스트 response를 반환한다.
from fastapi import FastAPI
from fastapi.responses import PlainTextResponse
app = FastAPI()
@app.get("/", response_class=PlainTextResponse)
async def main():
return "Hello World"
4) JSONResponse
- 일부 데이터를 가져와
application/json
으로 인코딩된 response를 반환한다.
5) ORJSONResponse
orjson
을 사용하여 JSON response를 반환한다.
6) UJSONResponse
ujson
을 사용하여 JSON response를 반환한다.
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"}]
7) RedirectResponse
- HTTP 리디렉션을 반환한다.
- 기본적으로 307 상태 코드를 사용한다.
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"
8) StreamingResponse
- async generator 또는 일반적인 generator/iterator를 사용하여 response body를 스트림한다.
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())
- 만약
open()
에 의해 반환된 객체인 file-like 객체가 있는 경우, 해당 file-like 객체를 반복하는 generator 함수를 생성할 수 있다. - 이런 방식을 이용하면, 메모리에서 모든 것을 읽을 필요가 없이 해당 generator 함수를
StreamingResponse
에 전달하고 반환할 수 있다.
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
app = FastAPI()
some_file_path = "large-video-file.mp4"
@app.get("/")
def main():
def iterfile():
with open(some_file_path, mode="rb") as file_like:
yield from file_like
return StreamingResponse(iterfile(), media_type="viedo/mp4")
9) FileResponse
- 비동기식으로 파일을 response로 스트림한다.
- 다음과 같은 인수를 사용하여 인스턴스화한다.
1] path
- 스트림할 파일의 경로이다.
2] headers
dict
타입의 사용자 정의 headers이다.
3] media_type
- media type을 제공하는 문자열이다.
4] filename
- 설정하면 response
Content-Disposition
에 포함된다.
- 또한 다음과 같이 적절한
Content-Length
,Last-Modified
및ETag
headers가 포함된다.
from fastapi import FastAPI
from fastapi.responses import FileResponse
app = FastAPI()
some_file_path = "large-video-file.mp4"
@app.get("/")
async def main():
return FileResponse(some_file_path)
- 매개변수
response_class
도 사용할 수 있다.
from fastapi import FastAPI
from fastapi.responses import FileResponse
app = FastAPI()
some_file_path = "large-video-file.mp4"
@app.get("/", response_class=FileResponse)
async def main():
return some_file_path
5. Default response class
- FastAPI 클래스 인스턴스 또는
APIRouter
를 생성할 때 기본적으로 사용할 response 클래스를 지정할 수 있다. - 이를 정의하는 매개변수는
default_response_class
이다.
- 다음과 같이 코드를 작성하면, FastAPI는 기본적으로 모든 path operations에서
JSONResponse
대신ORJSONResponse
를 사용하게 된다.
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"}]