If you want to affect the URL scheme for all server-generated URLs (url_for
and redirect
), rather than having to set _scheme
on every call, it seems that the "correct" answer is to use WSGI middleware, as in this snippet: http://flask.pocoo.org/snippets/35/
(This Flask bug seems to confirm that that is the preferred way.)
Basically, if your WSGI environment has environ['wsgi.url_scheme'] = 'https'
, then url_for
will generate https:
URLs.
I was getting http://
URLs from url_for
because my server was deployed behind an Elastic Beanstalk load balancer, which communicates with the server in regular HTTP. My solution (specific to Elastic Beanstalk) was like this (simplified from the snippet linked above):
class ReverseProxied(object):
def __init__(self, app):
self.app = app
def __call__(self, environ, start_response):
scheme = environ.get('HTTP_X_FORWARDED_PROTO')
if scheme:
environ['wsgi.url_scheme'] = scheme
return self.app(environ, start_response)
app = Flask(__name__)
app.wsgi_app = ReverseProxied(app.wsgi_app)
The Elastic Beanstalk-specific part of that is HTTP_X_FORWARDED_PROTO
. Other environments would have other ways of determining whether the external URL included https. If you just want to always use HTTPS, you could unconditionally set environ['wsgi.url_scheme'] = 'https'
.
PREFERRED_URL_SCHEME
is not the way to do this. It's ignored whenever a request is in progress.