10

How can I set an arbitrary attribute to the Request object from the middleware function?

from fastapi import FastAPI, Request

app = FastAPI()


@app.middleware("http")
async def set_custom_attr(request: Request, call_next):
    request.custom_attr = "This is my custom attribute"
    response = await call_next(request)
    return response


@app.get("/")
async def root(request: Request):
    return {"custom_attr": request.custom_attr}

This setup is raising an exception,

AttributeError: 'Request' object has no attribute 'custom_attr'

So, how can I get the "This is my custom attribute" value in my router?

JPG
  • 82,442
  • 19
  • 127
  • 206

1 Answers1

20

We can't attach/set an attribute to the request object (correct me if I am wrong).

But, we can make use of the Request.state--(Doc) property

from fastapi import FastAPI, Request

app = FastAPI()


@app.middleware("http")
async def set_custom_attr(request: Request, call_next):

    request.state.custom_attr = "This is my custom attribute" # setting the value to `request.state`

    response = await call_next(request)
    return response


@app.get("/")
async def root(request: Request):
    return {"custom_attr": request.state.custom_attr} # accessing the value from `request.state`
JPG
  • 82,442
  • 19
  • 127
  • 206
  • 3
    Well, you're attaching it to the request object. :P – Marcelo Trylesinski Nov 01 '20 at 22:35
  • 2
    To be more precise, this is a feature of starlette: https://www.starlette.io/requests/#other-state – kraxor May 29 '21 at 14:28
  • 1
    Thanks for this answer. It worked perfectly after hours of head banging. Perhaps worth quoting the FastAPI docs: "request.state is a property of each Request object. It is there to store arbitrary objects attached to the request itself, like the database session in this case." – Edward Gaere Feb 15 '22 at 18:15
  • Link to the aforementioned FastAPI documentation: https://fastapi.tiangolo.com/tutorial/sql-databases/#about-requeststate – jlhasson May 03 '22 at 02:47
  • @jlhasson, I hope the answer has the ***same*** reference already. – JPG May 03 '22 at 07:39