From fb3d368a784b1271089e900c519ade5c2f1fedb8 Mon Sep 17 00:00:00 2001 From: Ashley Sommer Date: Sun, 25 Oct 2020 05:57:02 +1000 Subject: [PATCH] Add ability for app.static() to return the routes it created. (#1954) This allows blueprint registration to add the bp's static routes to its list of own routes. So now blueprint middlewares will apply to a blueprint's static file routes. Fixes #1953 --- sanic/app.py | 5 +++-- sanic/blueprints.py | 19 +++++++++++-------- sanic/static.py | 5 ++++- tests/test_blueprints.py | 30 ++++++++++++++++++++++++++++++ 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/sanic/app.py b/sanic/app.py index 5f046a42..3f48f1fd 100644 --- a/sanic/app.py +++ b/sanic/app.py @@ -676,9 +676,10 @@ class Sanic: :param strict_slashes: Instruct :class:`Sanic` to check if the request URLs need to terminate with a */* :param content_type: user defined content type for header - :return: None + :return: routes registered on the router + :rtype: List[sanic.router.Route] """ - static_register( + return static_register( self, uri, file_or_directory, diff --git a/sanic/blueprints.py b/sanic/blueprints.py index cf5eee5e..09c54ffd 100644 --- a/sanic/blueprints.py +++ b/sanic/blueprints.py @@ -143,7 +143,18 @@ class Blueprint: if _routes: routes += _routes + # Static Files + for future in self.statics: + # Prepend the blueprint URI prefix if available + uri = url_prefix + future.uri if url_prefix else future.uri + _routes = app.static( + uri, future.file_or_directory, *future.args, **future.kwargs + ) + if _routes: + routes += _routes + route_names = [route.name for route in routes if route] + # Middleware for future in self.middlewares: if future.args or future.kwargs: @@ -160,14 +171,6 @@ class Blueprint: for future in self.exceptions: app.exception(*future.args, **future.kwargs)(future.handler) - # Static Files - for future in self.statics: - # Prepend the blueprint URI prefix if available - uri = url_prefix + future.uri if url_prefix else future.uri - app.static( - uri, future.file_or_directory, *future.args, **future.kwargs - ) - # Event listeners for event, listeners in self.listeners.items(): for listener in listeners: diff --git a/sanic/static.py b/sanic/static.py index 077d5a6d..c9c29fba 100644 --- a/sanic/static.py +++ b/sanic/static.py @@ -134,6 +134,8 @@ def register( threshold size to switch to file_stream() :param name: user defined name used for url_for :param content_type: user defined content type for header + :return: registered static routes + :rtype: List[sanic.router.Route] """ # If we're not trying to match a file directly, # serve from the folder @@ -155,10 +157,11 @@ def register( ) ) - app.route( + _routes, _ = app.route( uri, methods=["GET", "HEAD"], name=name, host=host, strict_slashes=strict_slashes, )(_handler) + return _routes diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py index 4978b51e..6e9fb20f 100644 --- a/tests/test_blueprints.py +++ b/tests/test_blueprints.py @@ -735,6 +735,36 @@ def test_static_blueprint_name(app: Sanic, static_file_directory, file_name): _, response = app.test_client.get("/static/test.file/") assert response.status == 200 +@pytest.mark.parametrize("file_name", ["test.file"]) +def test_static_blueprintp_mw(app: Sanic, static_file_directory, file_name): + current_file = inspect.getfile(inspect.currentframe()) + with open(current_file, "rb") as file: + file.read() + + triggered = False + + bp = Blueprint(name="test_mw", url_prefix="") + + @bp.middleware('request') + def bp_mw1(request): + nonlocal triggered + triggered = True + + bp.static( + "/test.file", + get_file_path(static_file_directory, file_name), + strict_slashes=True, + name="static" + ) + + app.blueprint(bp) + + uri = app.url_for("test_mw.static") + assert uri == "/test.file" + + _, response = app.test_client.get("/test.file") + assert triggered is True + def test_route_handler_add(app: Sanic): view = CompositionView()