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

Issues using flask-openapi3 when its views are decorated #143

Open
maldoinc opened this issue Feb 13, 2024 · 1 comment
Open

Issues using flask-openapi3 when its views are decorated #143

maldoinc opened this issue Feb 13, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@maldoinc
Copy link

Environment:

  • Python version: 312
  • Operating system:
  • Flask version:
  • flask-openapi3 version:

This affects all versions. Flask-openapi3 removes all arguments passed to the view by any previous callers -- such as Dependency Injection frameworks, breaking things in the meanwhile.

In request._validate_request all arguments kwargs are removed as they are treated as path args. This is however not always a correct assumption as views from flask-openapi3 may be decorated again before being passed onto flask.

In this case flask calls the views decorated elsewhere which supply some arguments to flask-openapi3 which then simply removes them instead of passing them down. There are a few flask extensions which do this as well.

In the below example the call chain is as follows flask -> inject_services -> flask_openapi3.

Example:

@app.get("/greet")
def view(greeter: GreeterService, query: GreetQuery):
    return greeter.greet(query.name)

...

# Automatically decorate all flask views so that known services are passed down.
app.view_functions = {k: inject_services(v) for k, v in app.view_functions.items()}

...
@maldoinc maldoinc added the bug Something isn't working label Feb 13, 2024
@github-actions github-actions bot added the Stale label May 1, 2024
@puittenbroek
Copy link

Not an entirely similar situation, but something that we run into.

We use decorators to provide authentication checks. A similar approach is flask-login.

@app.route("/settings")
@login_required
def settings():
    pass

Using this sort of set-up together with openapi3 means:

  1. flask handles incoming request (routing)
  2. flask-openapi3 checks incoming query-string, body, etc via the _validate_request (validation)
  3. decorators come into play (authorization)

Meaning our authentication decorator goes off AFTER the payload, query-string and all that has been checked.
So we get validation before authorization! Which is in my opinion a bad pattern.

Personally, I think it's better to first check;

  1. Route existence
  2. Authorization
  3. Validation

I don't see a easy solution to this, since the current set-up with _validate_request is on a high level.

Perhaps move the _validate_request logic into a decorator? Then we control the flow by the order of decorators.

Then you could remove all the validation_error_callback logic and just document how to catch ValidationError in a errorhandler on app level. Now you're trying to do everything, which isn't needed IMO.

@github-actions github-actions bot removed the Stale label Mar 1, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants