Skip to content

Flask Blueprints before_request not executed for call with bodies #2044

Open
@jledrumics

Description

@jledrumics

It seems that FlaskApp Blueprints before_request hooks are not executed for non-GET methods (OK for GET).
Flask app before_request hooks are well executed in their side.
It may not be considered as a bug if connexion is not aimed to work with flask hooks, and another mechanisms should be used.

TO REPRODUCE

Python 3.13.2
connexion 3.2.0
Flask 3.1.0

Run the following python file :

import connexion
from flask import Blueprint, jsonify, g
import tempfile

swagger_yaml = """
swagger: "2.0"
info:
  version: "1.0.0"
  title: "Test API"
paths:
  /blueprint/get:
    get:
      operationId: "example.bp_get_route"
      produces:
        - "application/json"
      responses:
        "200":
          description: "OK"
  /blueprint/post:
    post:
      operationId: "example.bp_post_route"
      consumes:
        - "application/json"
      produces:
        - "application/json"
      parameters:
        - in: "body"
          name: "payload"
          required: true
          schema:
            type: object
            properties:
              ifYouWant:
                type: string
      responses:
        "200":
          description: "OK"
  /post:
    post:
      operationId: "example.post_route"
      consumes:
        - "application/json"
      produces:
        - "application/json"
      parameters:
        - in: "body"
          name: "payload"
          required: true
          schema:
            type: object
            properties:
              ifYouWant:
                type: string
      responses:
        "200":
          description: "OK"
"""

with tempfile.NamedTemporaryFile("w", suffix=".yaml", delete=False) as tmp:
    tmp.write(swagger_yaml)
    swagger_file = tmp.name

ticket_bp = Blueprint("test", __name__, url_prefix="/blueprint")


@ticket_bp.before_request
def before_bp_hook():
    g.blueprint_hook_executed = True


@ticket_bp.route("/get")
def bp_get_route():
    bp_flag = g.get("blueprint_hook_executed", False)
    flag = g.get("hook_executed", False)
    return jsonify({"route": "BP GET", "hook_executed": flag, "blueprint_hook_executed": bp_flag})

# ticket_bp.route("/post", methods=["POST"])
@ticket_bp.route("/post")
def bp_post_route():
    bp_flag = g.get("blueprint_hook_executed", False)
    flag = g.get("hook_executed", False)
    is_bug = flag is False or bp_flag is False
    return jsonify({"route": "BP POST", "hook_executed": flag, "blueprint_hook_executed": bp_flag, "is_bug": is_bug})


def post_route():
    flag = g.get("hook_executed", False)
    is_bug = flag is False
    return jsonify({"route": "NORMAL POST", "hook_executed": flag, "is_bug": is_bug})


if __name__ == "__main__":
    app = connexion.FlaskApp(__name__, specification_dir=".")
    app.add_api(swagger_file, pythonic_params=True)
    app.app.register_blueprint(ticket_bp)

    @app.app.before_request
    def before_hook():
        g.hook_executed = True

    app.app.add_url_rule("/post", view_func=post_route)

    app.run(port=5000)

Then make the following calls :

curl -X POST http://localhost:5000/post  -H "Content-Type: application/json" -d '{}'
curl http://localhost:5000/blueprint/get
curl -X POST http://localhost:5000/blueprint/post -H "Content-Type: application/json" -d '{}'

MY WORKAROUND

By defining the method in the app.route decorator, the blueprint hook is executed. i.e @ticket_bp.route("/post", methods=["POST"]).
But I'm not sure whuy it needs to be redefined as it already is defined in swagger.

ADDITIONNAL INFOS

I tried to replicate the issue with flask only code, but it is not possible as Flask required the methods in the route definition (as not coming from a spec).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions