Reputation: 1815
I have a flask web app which uses render_template as follows.I need to add a Content-Security-Policy as additional http response headerin the response. I tried following ways but both fail and give me 500.
1.
from flask import \
Flask, \
render_template
app = Flask(__name__,template_folder='tmpl')
@app.route('/')
def index():
resp =make_response(render_template('index.html'))
resp.headers['Content-Security-Policy']='default-src \'self\''
return resp
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3001)
2.
@app.route('/')
def index():
resp =render_template('index.html')
resp.headers.add('Content-Security-Policy','default-src \'self\'')
return resp
if __name__ == '__main__':
app.run(host='0.0.0.0', port=3001)
What can be wrong here?
On the terminal i see following when I access the web app as localhost:3001
127.0.0.1 - - [06/Apr/2015 01:45:01] "GET / HTTP/1.1" 500 -
Upvotes: 12
Views: 34429
Reputation: 8117
The prettiest way to handle this, assuming that you want to same headers attached to all of your responses is with flasks builtin decorator:
@app.after_request
So in this case just add this function to your routes module:
@app.after_request
def add_security_headers(resp):
resp.headers['Content-Security-Policy']='default-src \'self\''
return resp
With this in place your functions just return the render_template(...) value as before and flask automatically wraps it in a response which is passed to the after_request function before being returned to the client.
Upvotes: 8
Reputation: 127180
render_template
returns a string, not a response. A string returned from a view is automatically wrapped in a response by Flask, which is why you may be confused. Construct the response with the rendered template.
from flask import make_response
r = make_response(render_template('index.html'))
r.headers.set('Content-Security-Policy', "default-src 'self'")
return r
Upvotes: 39