如何让 Cloudfront 到 return non-cached POST 上的原始页面

How to get Cloudfront to return non-cached Origin page on POST

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

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

我想使用 Cloudfront 进行自定义 domain/cert 但我不太在意缓存 - 如果有它会很好,但我希望我的应用程序正常运行!

我尝试过的:

1) 关于 Cloudfront Distribution >> 行为我尝试禁用所有缓存并允许 POST:

2) 在 Flask 应用程序中,我添加了代码以添加 no-cache header:

和下面的代码所述。

@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 文件的一部分,其中 return 是表单页面模板...

# 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在两种形式steps/loads之间没有变化。

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

我已经尝试在 Cloudfront 和 Origin 应用程序上禁用缓存,但看起来 Cloudfront 仍然在提供页面的缓存版本。

更新: 进一步的测试表明 form.validate_on_submit() 甚至 form.is_submitted() 都评估为 False。这解释了可观察到的操作,即页面只是重新加载表单,就好像表单尚未提交一样。我不明白为什么我会看到这种行为。我已经允许 POST 在 Cloudfront 分配上,但我是否需要在 Cloudfront 上设置其他内容以让它发送表单值?还是 Origin Web 服务器 (gunicorn 19.9.0) 上的某些东西正在删除表单详细信息?

更新 2: 我向应用程序添加了 Flask_cors 并向测试路由添加了 @cross_origin(allow_headers=['Content-Type']) 装饰器。同样的问题仍然存在。我不完全理解 CORS 问题,我以前从未使用过 Flask_cors 但希望这已经排除了 CORS 相关问题。如果更有经验的人认为这是与 CORS 相关的问题,我愿意对此进行更正。

更新 3(解决方法): 我用 if request.method == 'POST': 替换了 form.validate_on_submit(),应用程序似乎可以正常工作。

但是:

  1. 我仍然不明白为什么表格没有被 return 更正。谁能解释一下 Cloudfront 和 Heroku 之间可能发生的事情 App/webserver?

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

  3. 为什么 form.validate_on_submit()form.is_submitted() return false 但我可以通过 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

转发查询字符串:是