Skip to content
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

Update context throughout middleware stack? #1750

Open
RobbeSneyders opened this issue Oct 22, 2023 · 5 comments
Open

Update context throughout middleware stack? #1750

RobbeSneyders opened this issue Oct 22, 2023 · 5 comments

Comments

@RobbeSneyders
Copy link
Member

We currently set the Context variables offered to the user in the ContextMiddleware at the end of the stack, which makes them available in view functions and any code called from there.

In code called earlier in the middleware stack, such as the security functions for example, the context is not available.

Each middleware has access to all the information needed to set the context, so we could update the context in each middleware throughout the middleware stack to make it accessible to code running anywhere in the stack during a request.

Note that middlewares handling responses, such as the ResponseValidation, actually need this context when returning the response, so we might have to set and unset it as follows:

def __call__(self, scope, receive, send):
    # Set context variables
    # Logic working on requests
    # Unset context variables
    self.next_app(scope, receive, send)
    # Set context variables
    # Logic working on responses
    # Unset context variables
@SpudInNZ
Copy link

SpudInNZ commented Nov 1, 2023

Big +1 for this. This issue bit me quite hard when we were trying to move from a non-trivial Connexion 2 codebase to 3. I can't recall the workaround we had to do, but it wasn't pretty.

@explody
Copy link

explody commented Nov 9, 2023

Another big +1 on this. I'm working on a custom authentication scenario that needs access to the request context, to make authn and authz decisions based on data in the request.

@chbndrhnns
Copy link
Contributor

@SpudInNZ May I ask for your workaround? I need access to the request in the security middleware and currently I have no idea how to do that.

RobbeSneyders added a commit that referenced this issue Mar 20, 2024
Fixes #1881
Fixes #1880
Fixes #1876

Alternative to #1750

This PR makes the current request available to the security handlers by
injecting it as a keyword. I think this is a proper alternative to
#1750, since this is the only place in the default middleware stack
where I expect this to be needed.
@pradhan-v
Copy link

For middlewares inheriting the starlette.middleware.base.BaseHTTPMiddleware the context and the request object can be accessed with this workaround

from starlette.middleware.base import BaseHTTPMiddleware

class RequestIdMiddleware(BaseHTTPMiddleware):
    async def dispatch(self, request, call_next):
        request_id = request.headers.get("x-request-id")

        # FIXME: https://github.com/spec-first/connexion/issues/1750
        connexion_context = request.scope.get("extensions", {}).get("connexion_context", {})

        connexion_context["request_id"] = request_id
        response = await call_next(request)
        response.headers["request_id"] = request_id
        return response

@FelixSchwarz
Copy link
Contributor

I think this might be the core problem when migrating a flask-based connexion v2 app to v3. In our case, it would have been really beneficial if our security implementations could have access to the flask config/db. I think we could clean up our "integration code" quite a bit if connexion provided the scope to middlewares earlier in the stack.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants