pythonfastapiswagger-uiopenapiredoc

How to customize response messages for ReDoc OpenAPI documentation in FastAPI?


I have developed some FastAPI app, and want to customize its redoc documentation. Below is the code for it:

from fastapi import FastAPI
from typing import Optional

import uvicorn

app = FastAPI()

class User(BaseModel):
    username: str

user_list = ["John", "Abrahim", "Kiana"]

#Get method to fetch some value
@app.get('/user/{id}/')
def users(id:int):
    return user_list[id]

#Request Bodies
#Post Method
@app.post('/user')
def add_user(request:User):
    return request.username


if __name__ == "__main__":
    uvicorn.run(app, host="127.0.0.1",port=8000)

As of now I am getting below response in my redoc documentation: enter image description here

I want to add more response codes in redoc like below and also wants to customize the messages against each code. Not sure how to do, so please help in it.

200 - OK    Everything worked as expected.
400 - Bad Request   The request was unacceptable, often due to missing a required parameter.
401 - Unauthorized  No valid API key provided.
402 - Request Failed    The parameters were valid but the request failed.
403 - Forbidden The API key doesn't have permissions to perform the request.
404 - Not Found The requested resource doesn't exist.
409 - Conflict  The request conflicts with another request (perhaps due to using the same idempotent key).
429 - Too Many Requests Too many requests hit the API too quickly. We recommend an exponential backoff of your requests.
500, 502, 503, 504 - Server Errors  Something went wrong on Stripe's end. (These are rare.)

Solution

  • Straight from the documentation:

    You might want to have some predefined responses that apply to many path operations, but you want to combine them with custom responses needed by each path operation.

    For those cases, you can use the Python technique of "unpacking" a dict with **dict_to_unpack:

    json old_dict = {
        "old key": "old value",
        "second old key": "second old value", 
    } 
    new_dict = {**old_dict, "new key": "new value"} 
    

    Here, new_dict will contain all the key-value pairs from old_dict plus the new key-value pair:

    json {
        "old key": "old value",
        "second old key": "second old value",
        "new key": "new value", 
    } 
    

    You can use that technique to re-use some predefined responses in your path operations and combine them with additional custom ones.

    Working Example

    from typing import Union
    
    from fastapi import FastAPI
    from fastapi.responses import FileResponse
    from pydantic import BaseModel
    
    
    class Item(BaseModel):
        id: str
        value: str
    
    
    responses = {
        404: {"description": "Item not found"},
        302: {"description": "The item was moved"},
        403: {"description": "Not enough privileges"},
    }
    
    
    app = FastAPI()
    
    
    @app.get(
        "/items/{item_id}",
        response_model=Item,
        responses={**responses, 200: {"content": {"image/png": {}}}},
    )
    async def read_item(item_id: str, img: Union[bool, None] = None):
        if img:
            return FileResponse("image.png", media_type="image/png")
        else:
            return {"id": "foo", "value": "there goes my hero"}