Skip to content

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Equivalent of flask's Flask.before_request and Flask.after_request? #409

Closed
cetanu opened this issue Jul 26, 2019 · 6 comments
Closed

Equivalent of flask's Flask.before_request and Flask.after_request? #409

cetanu opened this issue Jul 26, 2019 · 6 comments

Comments

@cetanu
Copy link

cetanu commented Jul 26, 2019

Hello,

Is it possible to register functions to be run before and after a request, similar to in flask?

Are you familiar with how this works, and is there an equivalent in FastAPI/Starlette?

@cetanu cetanu added the question Question or problem label Jul 26, 2019
@dmontagu
Copy link
Collaborator

dmontagu commented Jul 26, 2019

I haven't used flask much, but looking through the flask docs a little, this seems to be the same concept as middleware.

Here are the middleware docs for FastAPI, and for starlette.

For example, looking at an example from the SQL Databases page from the FastAPI docs (linked from the middleware link above), here's a way to use this to handle a database session at the start and end of each request:

@app.middleware("http")
async def db_session_middleware(request: Request, call_next):
    response = Response("Internal server error", status_code=500)
    try:
        request.state.db = SessionLocal()
        response = await call_next(request)
    finally:
        request.state.db.close()
    return response

I think that flask.before_request basically corresponds to the code prior to the response = await call_next(request) line, and flask.after_request corresponds to the part afterward.

@cetanu
Copy link
Author

cetanu commented Jul 29, 2019

That's perfect, and very neat in comparison.

My use case is to add JSON logging which takes context from the request/response.

I was able to achieve it with the following example

import structlog
from fastapi import FastAPI
from starlette.requests import Request
from starlette.responses import Response

structlog.configure(
    processors=[
        structlog.processors.JSONRenderer()
    ]
)
logger = structlog.get_logger()

app = FastAPI()

@app.middleware('http')
async def logging_middleware(request: Request, call_next):
    response = Response("Internal server error", status_code=500)
    log = logger.bind(
        url=str(request.url),
        method=request.method,
    )
    try:
        response: Response = await call_next(request)
    finally:
        log.msg(
            status=response.status_code,
        )
    return response

@cetanu cetanu closed this as completed Jul 29, 2019
@tiangolo
Copy link
Member

Thanks for the help as always @dmontagu ! 🍰 🎉

Thanks @cetanu for reporting back and closing the issue ✔️

@hongymagic
Copy link

@cetanu does that logging with structlog work correctly? I'm finding that, parallel requests mix up the context - where bound context (in your case, url and method) end up spanning across the different request/response cycle. Even when I'm using structlog's threaded local dict + context manager.

@cetanu
Copy link
Author

cetanu commented Sep 10, 2019

@hongymagic
This is something I set up for a colleague, I haven't heard any reports of such behavior and from what I've seen it seems to be working as expected... As long as you're not accidentally binding to a logger used in an outer scope I imagine it should be okay?

@hongymagic
Copy link

It was a pretty similar setup to above, except in our case we use (or generate) a X-Request-Id and add it to the structlog's context.

We ended up solving it, see: hynek/structlog#222

@tiangolo tiangolo changed the title [QUESTION] Equivalent of flask's Flask.before_request and Flask.after_request? Equivalent of flask's Flask.before_request and Flask.after_request? Feb 24, 2023
@tiangolo tiangolo reopened this Feb 28, 2023
@fastapi fastapi locked and limited conversation to collaborators Feb 28, 2023
@tiangolo tiangolo converted this issue into discussion #8200 Feb 28, 2023

This issue was moved to a discussion.

You can continue the conversation there. Go to discussion →

Projects
None yet
Development

No branches or pull requests

4 participants