diff --git a/flask/blueprints.py b/flask/blueprints.py index 0a6ccfb7..8311e580 100644 --- a/flask/blueprints.py +++ b/flask/blueprints.py @@ -49,12 +49,10 @@ class BlueprintSetupState(object): url_prefix = self.options.get('url_prefix') if url_prefix is None: url_prefix = self.blueprint.url_prefix - + if url_prefix: + url_prefix = url_prefix.rstrip('/') #: The prefix that should be used for all URLs defined on the #: blueprint. - if url_prefix and url_prefix[-1] == '/': - url_prefix = url_prefix[:-1] - self.url_prefix = url_prefix #: A dictionary with URL defaults that is added to each and every @@ -68,7 +66,7 @@ class BlueprintSetupState(object): blueprint's name. """ if self.url_prefix: - rule = self.url_prefix + rule + rule = '/'.join((self.url_prefix, rule.lstrip('/'))) options.setdefault('subdomain', self.subdomain) if endpoint is None: endpoint = _endpoint_from_view_func(view_func) diff --git a/tests/test_blueprints.py b/tests/test_blueprints.py index a2631241..46364cab 100644 --- a/tests/test_blueprints.py +++ b/tests/test_blueprints.py @@ -115,17 +115,22 @@ def test_blueprint_app_error_handling(app, client): assert client.get('/nope').data == b'you shall not pass' -def test_blueprint_prefix_slash(app, client): - bp = flask.Blueprint('test', __name__, url_prefix='/bar/') - - @bp.route('/foo') - def foo(): +@pytest.mark.parametrize(('prefix', 'rule', 'url'), ( + ('/foo/', '/bar', '/foo/bar'), + ('/foo/', 'bar', '/foo/bar'), + ('/foo', '/bar', '/foo/bar'), + ('/foo/', '//bar', '/foo/bar'), + ('/foo//', '/bar', '/foo/bar'), +)) +def test_blueprint_prefix_slash(app, client, prefix, rule, url): + bp = flask.Blueprint('test', __name__, url_prefix=prefix) + + @bp.route(rule) + def index(): return '', 204 app.register_blueprint(bp) - app.register_blueprint(bp, url_prefix='/spam/') - assert client.get('/bar/foo').status_code == 204 - assert client.get('/spam/foo').status_code == 204 + assert client.get(url).status_code == 204 def test_blueprint_url_defaults(app, client):