python-3.x - 如何让 Cloudfront 在 POST 上返回非缓存的原始页面
问题描述
我正在使用 Cloudfront 为 Heroku(免费层)上托管的 Flask 应用程序提供自定义域和关联的 TLS 证书。我有一个表单,它发布用户的输入,由 Flask 应用程序处理。基于输入和成功的表单验证,一个新的模板被呈现,进一步的用户信息被收集(即两步表单)。
在本地测试或直接访问 Heroku 应用程序(example_app.herokuapp.com)时,一切正常。当我通过自定义 URL/Cloudfront 进行测试时,页面只是重新加载第一个表单步骤。
我想将 Cloudfront 用于自定义域/证书,但我不太担心缓存 - 很高兴,但我宁愿我的应用程序正常工作!
我试过的:
1)在 Cloudfront Distribution >> Behaviors 我试图禁用所有缓存并允许 POST:
允许的 HTTP 方法:GET、HEAD、OPTIONS、PUT、POST、PATCH、DELETE
基于选定请求标头的缓存:全部
对象缓存:自定义
最小 TTL:0
最大 TTL:0
默认 TTL:0
查询字符串转发和缓存:转发全部,基于全部缓存
2)在 Flask 应用程序中,我添加了代码以添加无缓存标头:
如此处所述和下面的代码。
@bp.after_request
def add_header(r):
r.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
r.headers["Pragma"] = "no-cache"
r.headers["Expires"] = "0"
return r
这是我的 Flask Routes 文件的部分,它返回表单页面模板...
# Route for activation form page
@bp.route('/activate/', methods=['GET', 'POST'])
def activate():
form = ActivateForm()
if form.validate_on_submit():
# Get the details entered by the customer
email = form.email.data
value2 = form.value2.data
# Check that input is valid
result = check_valid(value2)
# if valid
if result['status'] == 1:
# do stuff to activate subscription and assign sub_id
# Redirect to sucessful activation page
return render_template('finish.html', title='Finalising your subscription', sub_id=sub_id, email=email)
# if the form isn't valid or hasn't been submitted...
return render_template('activate.html', title='Activate', form=form)
当我在本地测试或直接针对 Heroku(example_app.herokuapp.com)进行测试时,一切都按预期工作:
在初始页面访问或表单内容无效时,将加载 activate.html 模板。
在提交有效表单时,
if result['status'] == 1:
运行中的说明和 finish.html 模板会加载。
注意:页面 URL 在两个表单步骤/加载之间不会更改。
但是,当我尝试通过 Cloudfront 访问应用程序时:
在初始页面访问或表单内容无效时,activate.html 模板会按预期加载。
提交有效表单后,activate.html 模板会再次加载,并且
if result['status'] == 1:
不会执行其中的指令。
我已经尝试在 Cloudfront 和 Origin 应用程序上禁用缓存,但看起来 Cloudfront 仍在提供页面的缓存版本。
更新:进一步的测试表明,form.validate_on_submit()
甚至form.is_submitted()
两者都评估为 False。这解释了页面只是重新加载表单的可观察操作,就好像它还没有提交一样。我不明白为什么我会看到这种行为。我已允许在 Cloudfront 分发上进行 POST,但我是否需要在 Cloudfront 上设置其他内容以使其发送表单值?还是 Origin Web 服务器(gunicorn 19.9.0)上的某些东西正在删除表单详细信息?
更新 2:我将 Flask_cors 添加到应用程序中,并将@cross_origin(allow_headers=['Content-Type'])
装饰器添加到测试路由中。同样的问题仍然存在。我不完全理解 CORS 问题,而且我以前从未使用过 Flask_cors,但希望这已经排除了与 CORS 相关的问题。如果更有经验的人认为这是与 CORS 相关的问题,我愿意对此进行更正。
更新 3(解决方法):我替换form.validate_on_submit()
为if request.method == 'POST':
并且应用程序似乎正在运行。
然而:
我仍然不明白为什么表格没有被返回更正。谁能解释 Cloudfront 和 Heroku 应用程序/网络服务器之间可能发生的事情?
仅使用有什么缺点
if request.method == 'POST':
吗?手动替换表单验证的最佳做法是什么?我是否需要验证(猜测是,但我需要测试以查看是否可以在没有 的情况下破坏应用程序form.validate_on_submit()
)?为什么返回 false 但我可以通过 等访问所有表单
form.validate_on_submit()
值?form.is_submitted()
value2 = form.value2.data
更新 4:标记 Flask-WFT,因为这里可能有is_submitted()
问题。
解决方案
一直没搞清楚具体是什么问题。我删除并重新创建了 Cloudfront,Flask-WFT is_submitted() 开始按预期工作。所以......也许我的原始配置有一个类型或在某些方面有所不同?
如果对任何人有帮助,这是当前的 Cloudfront 配置...
交付方式:网络
Cookie 记录:关闭
自定义 SSL 客户端支持:支持服务器名称指示 (SNI) 的客户端 -(推荐)
安全策略:TLSv1.2_2018
支持的 HTTP 版本:HTTP/1.1、HTTP/1.0
源协议策略:仅 HTTPS
源响应超时:30
Origin Kepp-alive 超时:5
查看器协议策略:将 HTTP 重定向到 HTTPS
转发查询字符串:是
推荐阅读
- hashicorp-vault - 系统重新启动后无法解封 hashcorp 保管库
- mysql - 从两个mysql表中选择值
- ios - 如何摆脱distribution.plist的UUID?
- c# - 在 asp.net mvc 和 mongodb 中自动跟踪创建和修改的字段
- javascript - jQuery:显示侧边栏,推开主要区域
- node.js - 按子项排序值
- python - 在 Python 中通过 `subprocess.run` 调用 g++ 会导致可执行文件中出现“exec 格式错误”
- c# - 如果 api 不可用,WPF 应用程序不会运行(或出现)
- javascript - 在 Discord.js 上进行嵌入
- python - 创建一个python GUI计算器,但平方根函数给我带来了问题