Атрибут state класса Request
Атрибут state принадлежит объекту Request и представляет собой объект State, в который можно записывать произвольные атрибуты. Он применяется для передачи данных между middleware, зависимостями и функцией-обработчиком в рамках одного запроса. По умолчанию объект state пуст, а значения в него добавляются вручную через точечную нотацию. Так как объект привязан к конкретному запросу, данные не разделяются между разными запросами.
Синтаксис
request.state.attribute_name
Синтаксис чтения значения из атрибута:
value = request.state.attribute_name
Синтаксис записи значения в атрибут:
request.state.attribute_name = value
Пример
Давайте запишем значение в state внутри middleware и прочитаем его в обработчике:
from fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")
async def add_data(request: Request, call_next):
request.state.user = 'abcde'
response = await call_next(request)
return response
@app.get('/')
async def index(request: Request):
return {'user': request.state.user}
Результат выполнения кода для адреса /:
{"user": "abcde"}
Пример
Давайте проверим, что state не разделяется между разными запросами:
from fastapi import FastAPI, Request
app = FastAPI()
@app.middleware("http")
async def add_counter(request: Request, call_next):
request.state.counter = 1
response = await call_next(request)
return response
@app.get('/first')
async def first(request: Request):
request.state.counter = 5
return {'counter': request.state.counter}
@app.get('/second')
async def second(request: Request):
return {'counter': request.state.counter}
Результат выполнения кода для адреса /first:
{"counter": 5}
Результат выполнения кода для адреса /second:
{"counter": 1}
Как видно из примера, изменение state в обработчике /first не повлияло на значение в обработчике /second, потому что каждый запрос получает собственный объект state.
Пример
Давайте сохраним в state объект пользователя и передадим его в зависимость:
from fastapi import FastAPI, Request, Depends
app = FastAPI()
async def get_current_user(request: Request):
return request.state.current_user
@app.middleware("http")
async def load_user(request: Request, call_next):
request.state.current_user = {'id': 1, 'name': 'abcde'}
response = await call_next(request)
return response
@app.get('/me')
async def me(user: dict = Depends(get_current_user)):
return user
Результат выполнения кода для адреса /me:
{"id": 1, "name": "abcde"}