When I attempt to redirect incoming traffic to https I get an infinite redirect loop.
@app.route('/checkout/')
def checkout():
checkout = "https://myapp.herokuapp.com/checkout/"
if checkout != request.url:
print checkout, request.url
return redirect(checkout)
return render_template('checkout.html', key=keys['publishable_key'])
The request.url is never changed to prefix https. I want to use heroku's piggyback ssl to minimize cost.
1) Do "pip install flask-sslify"
(github is here: https://github.com/kennethreitz/flask-sslify )
2) Include the following lines:
from flask_sslify import SSLify
if 'DYNO' in os.environ: # only trigger SSLify if the app is running on Heroku
sslify = SSLify(app)
On Heroku, SSL (https) is terminated before it reaches your application, so you app never actually sees SSL traffic. To check whether a request was made with https, you instead have to inspect the x-forwarded-proto
header. More info here: How to make python on Heroku https only?
UPDATE: For your use, you should just check request.url for "myapp.herokuapp.com/checkout/"; and verify that the header is "https"
I tried SSLify, url_for _scheme, and setting a PREFERRED_URL_SCHEME; however none worked out, at the release level at least.. (worked fine locally) Then I thought;
@app.before_request
def beforeRequest():
if not request.url.startswith('https'):
return redirect(request.url.replace('http', 'https', 1))
This is essentially another way to get it done without any configurations, or extensions.
I was able to repurpose the flask-sslify code for a single view. Just needed to check whether or not the request was being made with SSL and add proper headers to the response. https://github.com/kennethreitz/flask-sslify
@app.route('/checkout/')
def checkout():
checkout = "https://myapp.herokuapp.com/checkout/"
if request.headers.get('X-Forwarded-Proto', 'http') == 'https':
resp = make_response(render_template('checkout.html', key=keys['publishable_key']))
return set_hsts_header(resp)
return redirect(checkout, code=302)
def set_hsts_header(response):
"""Adds HSTS header to each response."""
response.headers.setdefault('Strict-Transport-Security', hsts_header)
return response
def hsts_header():
"""Returns the proper HSTS policy."""
hsts_policy = 'max-age={0}'.format(31536000) #year in seconds
if self.hsts_include_subdomains:
hsts_policy += '; includeSubDomains'
return hsts_policy
You just need to check the X-Forwarded-Proto
header. If its false, redirect to the equivalent https url.
Here the code to enforce https for all calls on a flask app running on heroku:
@app.before_request
def enforceHttpsInHeroku():
if request.headers.get('X-Forwarded-Proto') == 'http':
url = request.url.replace('http://', 'https://', 1)
code = 301
return redirect(url, code=code)
You can do something like this:
@app.before_request
def before_request():
if 'DYNO' in os.environ: # Only runs when on heroku
if request.url.startswith('http://'):
url = request.url.replace('http://', 'https://', 1)
code = 301
return redirect(url, code=code)
On my answer to another question I have stated the upto date Flask recommendations. Use Talisman instead of SSLify.
For Flask use Talisman . Flask , Heroku and SSLify documentations favor the use of Talisman over SSLify because the later is no longer maintained.
From SSLify :
The extension is no longer maintained, prefer using Flask-Talisman as it is encouraged by the Flask Security Guide.
Install via pip:
$ pip install flask-talisman
Instatiate the extension (example):
from flask import Flask from flask_talisman import Talisman app = Flask(__name__) if 'DYNO' in os.environ: Talisman(app)
Talisman enables CSP (Content Security Policy) by default only allowing resources from the same domain to be loaded. If you want to disable it and deal with the implications:
Talisman(app, content_security_policy=None)
If you don't want to disable it you have set the
content_security_policy
argument to allow resources from external domains, like CDNs, for instance. For that refer to the documentation .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.