Skip to content

FastAPI Response Handling

1. Declaration of Response Status Codes

Declare HTTP status codes through the status_code parameter of the route decorator:

python
from fastapi import FastAPI, status

app = FastAPI()

@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(name: str):
    return {"name": name}

Status Code Specifications

CategoryTypical CodeDescriptionResponse Body Requirement
Success200 OKDefault successMust be included
201 CreatedResource created successfullyOptional
204 No ContentNo content returnedProhibited to include
Redirection307 Temporary RedirectTemporary redirectionOptional
Client Error400 Bad RequestInvalid requestMust include error information
404 Not FoundResource not foundMust include error information

Status Code Shortcuts

Use predefined enumeration values:

python
from fastapi import status

@app.delete("/items/{id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(id: int):
    pass  # No response body

2. Detailed Explanation of Response Types

JSON Response
Automatic Serialization
python
@app.get("/data")
def get_data():
    return {
        "user": {
            "id": 123,
            "name": "Alice"
        }
    }
Custom Response
python
from fastapi.responses import JSONResponse

@app.get("/custom-json")
def custom_json():
    return JSONResponse(
        content={"message": "Hello"},
        status_code=status.HTTP_200_OK,
        headers={"X-Custom-Header": "fastapi"}
    )
HTML Response
python
from fastapi.responses import HTMLResponse

@app.get("/page", response_class=HTMLResponse)
async def show_page():
    return """
    <html>
        <head>
            <title>FastAPI Page</title>
        </head>
        <body>
            <h1>Welcome to FastAPI!</h1>
        </body>
    </html>
    """
File Response
python
from fastapi.responses import FileResponse

@app.get("/download")
async def download_file():
    return FileResponse(
        path="document.pdf",
        filename="report.pdf",
        media_type="application/pdf"
    )
Streaming Response
python
from fastapi.responses import StreamingResponse
import asyncio

async def stream_data():
    for i in range(5):
        yield f"Chunk {i}\n".encode()
        await asyncio.sleep(1)

@app.get("/stream")
async def get_stream():
    return StreamingResponse(
        stream_data(),
        media_type="text/plain"
    )
Redirect Response
python
from fastapi.responses import RedirectResponse

@app.get("/redirect")
async def redirect_to_docs():
    return RedirectResponse(
        url="https://fastapi.tiangolo.com",
        status_code=status.HTTP_302_FOUND
    )

3. Response Header Control

python
@app.get("/headers")
def get_headers():
    return JSONResponse(
        content={"message": "Header demo"},
        headers={
            "X-Rate-Limit": "5000/day",
            "Cache-Control": "max-age=3600"
        }
    )

4. Response Media Types

Response TypeMedia TypeTypical Use Cases
JSONResponseapplication/jsonAPI data interaction
HTMLResponsetext/htmlPage rendering
FileResponseimage/jpegImage download
StreamingResponseapplication/octet-streamLarge file transfer

5. Advanced Response Modes

python
from fastapi.responses import ORJSONResponse

@app.get("/orjson", response_class=ORJSONResponse)
def get_orjson():
    return {"data": [1, 2, 3]}

6. Best Practice Recommendations

  • Status Code Specification:

    • Use 200/201 for successful operations.
    • Use 204 for resource deletion.
    • Use the 400 series for client errors.
    • Keep the default 500 for server errors.
  • Response Body Design:

python
from pydantic import BaseModel
from typing import Optional, Any

class SuccessResponse(BaseModel):
    code: int = 200
    message: str = "Success"
    data: Optional[Any] = None

@app.get("/api")
def get_api():
    return SuccessResponse(data={"key": "value"})
  • Performance Optimization:
python
@app.get("/large-data")
async def get_large_data():
    return StreamingResponse(
        get_large_file(),
        media_type="application/octet-stream"
    )
  • Error Handling:
python
@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail}
    )

By reasonably using response types and status codes, and combining FastAPI's automatic documentation and data validation functions, you can build robust and RESTful API interfaces.

Complete code example:

python
from fastapi import FastAPI, status, HTTPException
from fastapi.responses import JSONResponse, HTMLResponse, FileResponse, StreamingResponse, RedirectResponse, ORJSONResponse
from typing import Optional, Any
import asyncio

# Initialize the FastAPI application
app = FastAPI()

# 1. Declaration of Response Status Codes
@app.post("/items/", status_code=status.HTTP_201_CREATED)
async def create_item(name: str):
    """
    Create a new item and return the name of the created item.
    :param name: The name of the item.
    :return: A dictionary containing the name of the item.
    """
    return {"name": name}

@app.delete("/items/{id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_item(id: int):
    """
    Delete an item with the specified ID, no response body.
    :param id: The ID of the item.
    """
    pass

# 2. Detailed Explanation of Response Types
# 2.1 JSON Response
@app.get("/data")
def get_data():
    """
    Get user data and return it in JSON format.
    :return: A dictionary containing user information.
    """
    return {
        "user": {
            "id": 123,
            "name": "Alice"
        }
    }

@app.get("/custom-json")
def custom_json():
    """
    Return a custom JSON response containing custom response headers.
    :return: A JSON response object.
    """
    return JSONResponse(
        content={"message": "Hello"},
        status_code=status.HTTP_200_OK,
        headers={"X-Custom-Header": "fastapi"}
    )

# 2.2 HTML Response
@app.get("/page", response_class=HTMLResponse)
async def show_page():
    """
    Display a simple HTML page.
    :return: The content of the HTML page.
    """
    return """
    <html>
        <head>
            <title>FastAPI Page</title>
        </head>
        <body>
            <h1>Welcome to FastAPI!</h1>
        </body>
    </html>
    """

# 2.3 File Response
@app.get("/download")
async def download_file():
    """
    Download a PDF file.
    :return: A file response object.
    """
    return FileResponse(
        path="document.pdf",
        filename="report.pdf",
        media_type="application/pdf"
    )

# 2.4 Streaming Response
async def stream_data():
    """
    Simulate streaming data generation.
    :return: A generator that generates a data chunk each time.
    """
    for i in range(5):
        yield f"Chunk {i}\n".encode()
        await asyncio.sleep(1)

@app.get("/stream")
async def get_stream():
    """
    Return a streaming response.
    :return: A streaming response object.
    """
    return StreamingResponse(
        stream_data(),
        media_type="text/plain"
    )

# 2.5 Redirect Response
@app.get("/redirect")
async def redirect_to_docs():
    """
    Redirect to the official FastAPI documentation.
    :return: A redirect response object.
    """
    return RedirectResponse(
        url="https://fastapi.tiangolo.com",
        status_code=status.HTTP_302_FOUND
    )

# 3. Response Header Control
@app.get("/headers")
def get_headers():
    """
    Return a JSON response containing custom response headers.
    :return: A JSON response object.
    """
    return JSONResponse(
        content={"message": "Header demo"},
        headers={
            "X-Rate-Limit": "5000/day",
            "Cache-Control": "max-age=3600"
        }
    )

# 4. Advanced Response Modes
@app.get("/orjson", response_class=ORJSONResponse)
def get_orjson():
    """
    Return JSON data using ORJSONResponse.
    :return: A dictionary containing data.
    """
    return {"data": [1, 2, 3]}

# 5. Best Practice Recommendations
from pydantic import BaseModel

class SuccessResponse(BaseModel):
    """
    A unified success response model.
    """
    code: int = 200
    message: str = "Success"
    data: Optional[Any] = None

@app.get("/api")
def get_api():
    """
    Return data using the unified success response model.
    :return: An instance of the success response model.
    """
    return SuccessResponse(data={"key": "value"})

@app.get("/large-data")
async def get_large_data():
    """
    Handle large data requests using a streaming response.
    :return: A streaming response object.
    """
    return StreamingResponse(
        stream_data(),
        media_type="application/octet-stream"
    )

@app.exception_handler(HTTPException)
async def http_exception_handler(request, exc):
    """
    Handle HTTP exceptions and return a JSON response containing error information.
    :param request: The request object.
    :param exc: The exception object.
    :return: A JSON response object.
    """
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail}
    )

上次更新于: