Description
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).