adding _scheme parameter to url_for

In order to better facilitate generation of URLs that make use of an HTTPS URL
scheme this patch adds a parameter with this specific purpose in mind. To
achieve this we explicitly pass in a param, `_scheme='https'`, and then set the
`url_scheme` attribute of our `MapAdapter` instance appropriately.

Importantly, `_external=True` must be set in order for this to work properly.
As such, failure to do so results in a `ValueError` being raised.
This commit is contained in:
Max Countryman 2013-01-17 15:08:45 -08:00
parent 61d3bbf1d2
commit b5069d07a2
2 changed files with 34 additions and 0 deletions

View file

@ -229,6 +229,9 @@ def url_for(endpoint, **values):
that this is for building URLs outside the current application, and not for that this is for building URLs outside the current application, and not for
handling 404 NotFound errors. handling 404 NotFound errors.
.. versionadded:: 0.10
The `_scheme` parameter was added.
.. versionadded:: 0.9 .. versionadded:: 0.9
The `_anchor` and `_method` parameters were added. The `_anchor` and `_method` parameters were added.
@ -241,6 +244,8 @@ def url_for(endpoint, **values):
:param _external: if set to `True`, an absolute URL is generated. Server :param _external: if set to `True`, an absolute URL is generated. Server
address can be changed via `SERVER_NAME` configuration variable which address can be changed via `SERVER_NAME` configuration variable which
defaults to `localhost`. defaults to `localhost`.
:param _scheme: a string specifying the desired URL scheme. The `_external`
parameter must be set to `True` or a `ValueError` is raised.
:param _anchor: if provided this is added as anchor to the URL. :param _anchor: if provided this is added as anchor to the URL.
:param _method: if provided this explicitly specifies an HTTP method. :param _method: if provided this explicitly specifies an HTTP method.
""" """
@ -283,7 +288,14 @@ def url_for(endpoint, **values):
anchor = values.pop('_anchor', None) anchor = values.pop('_anchor', None)
method = values.pop('_method', None) method = values.pop('_method', None)
scheme = values.pop('_scheme', None)
appctx.app.inject_url_defaults(endpoint, values) appctx.app.inject_url_defaults(endpoint, values)
if scheme is not None:
if not external:
raise ValueError('When specifying _scheme, _external must be True')
url_adapter.url_scheme = scheme
try: try:
rv = url_adapter.build(endpoint, values, method=method, rv = url_adapter.build(endpoint, values, method=method,
force_external=external) force_external=external)

View file

@ -397,6 +397,28 @@ class LoggingTestCase(FlaskTestCase):
self.assert_equal(flask.url_for('index', _anchor='x y'), self.assert_equal(flask.url_for('index', _anchor='x y'),
'/#x%20y') '/#x%20y')
def test_url_for_with_scheme(self):
app = flask.Flask(__name__)
@app.route('/')
def index():
return '42'
with app.test_request_context():
self.assert_equal(flask.url_for('index',
_external=True,
_scheme='https'),
'https://localhost/')
def test_url_for_with_scheme_not_external(self):
app = flask.Flask(__name__)
@app.route('/')
def index():
return '42'
with app.test_request_context():
self.assert_raises(ValueError,
flask.url_for,
'index',
_scheme='https')
def test_url_with_method(self): def test_url_with_method(self):
from flask.views import MethodView from flask.views import MethodView
app = flask.Flask(__name__) app = flask.Flask(__name__)