首页 > 解决方案 > 如何让 Cloudfront 在 POST 上返回非缓存的原始页面

问题描述

我正在使用 Cloudfront 为 Heroku(免费层)上托管的 Flask 应用程序提供自定义域和关联的 TLS 证书。我有一个表单,它发布用户的输入,由 Flask 应用程序处理。基于输入和成功的表单验证,一个新的模板被呈现,进一步的用户信息被收集(即两步表单)。

在本地测试或直接访问 Heroku 应用程序(example_app.herokuapp.com)时,一切正常。当我通过自定义 URL/Cloudfront 进行测试时,页面只是重新加载第一个表单步骤。

我想将 Cloudfront 用于自定义域/证书,但我不太担心缓存 - 很高兴,但我宁愿我的应用程序正常工作!

我试过的:

1)在 Cloudfront Distribution >> Behaviors 我试图禁用所有缓存并允许 POST:

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)进行测试时,一切都按预期工作:

注意:页面 URL 在两个表单步骤/加载之间不会更改。

但是,当我尝试通过 Cloudfront 访问应用程序时:

我已经尝试在 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':并且应用程序似乎正在运行。

然而:

  1. 我仍然不明白为什么表格没有被返回更正。谁能解释 Cloudfront 和 Heroku 应用程序/网络服务器之间可能发生的事情?

  2. 仅使用有什么缺点if request.method == 'POST':吗?手动替换表单验证的最佳做法是什么?我是否需要验证(猜测是,但我需要测试以查看是否可以在没有 的情况下破坏应用程序form.validate_on_submit())?

  3. 为什么返回 false 但我可以通过 等访问所有表单form.validate_on_submit()值?form.is_submitted()value2 = form.value2.data

更新 4:标记 Flask-WFT,因为这里可能有is_submitted()问题。

标签: python-3.xamazon-cloudfrontflask-wtformsflask-cors

解决方案


一直没搞清楚具体是什么问题。我删除并重新创建了 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

转发查询字符串:是


推荐阅读