【问题标题】:Modify HTML Response (Not Headers)修改 HTML 响应(不是标头)
【发布时间】:2020-07-29 02:12:13
【问题描述】:

希望有人可以帮助我或为我指明正确的方向。

有人要求我了解如何让 Akamai(或任何其他 CDN 或 NGINX)修改实际响应正文。

为什么?

我要让 CDN 将所有“http://”请求更改为“https://”,而不是修改 App 代码以使用“//”进行外部资源请求。

这可能吗?

有人知道吗?

【问题讨论】:

    标签: nginx amazon-cloudfront akamai


    【解决方案1】:

    这似乎是可能通过许多不同的方法,但这并不是说它实际上可能是可取的

    这似乎存在潜在问题(例如:如果您重写不应该重写的东西怎么办?)和机器资源密集型(大量 CPU 周期来反复解析和处理响应正文)。

    这是我发现的:

    Nginx 有 http_sub_module 似乎以一种相当简单的方式完成此操作,假设您要替换的内容很简单,并且您只需要每页匹配一个模式,例如将 <a href="http://example.com/... 替换为 <a href="https://example.com/...,一个或更多次。这种内容杂乱无章似乎很粗略,但根据您所处的情况(可能是对应用程序的有限控制之一),它可能让您到达那里。

    看起来有一个叫做http_substitutions_filter的东西,可能是非官方的,或者至少不是核心 Nginx 发行版的一部分,它可以对响应体进行更强大的基于过滤器的重写。

    Varnish seems to have 具有类似的功能(可能是一个插件),但 HAProxy doesn't,因为它只处理标头并单独保留正文,除非在执行 gzip 卸载时。其他支持反向代理的软件(如 Apache 或 Squid)也可能提供一些有用的东西,您可以将它们放在应用程序服务器前面。

    无论如何,我最初的印象是,简单的字符串替换可能无法让你达到目标,即使基于正则表达式的替换也不够,因为正则表达式没有显着复杂性,因为你总是冒着重写的风险你不应该的东西。

    为了以最正确的方式实现这一目的,我建议“真正需要发生”的是使用 DOM 解析库实际解释生成的 HTML,遍历树,并修改相关元素 -在将修改后的文件交给请求者之前。这样,文档会根据对其内容的上下文理解进行修改。

    在我看来,这听起来很复杂,因为它是 -- 所以我再次建议您重新考虑您计划的方法,除非这超出了您的控制范围。

    最后的想法:好奇心战胜了我,所以我接受了这个问题并改进了我编写的 http 反向代理(用于不同的目的),以便根据内容类型,它实际上可以解析和遍历 HTML结构作为一个适当的实体,在将响应正文返回给请求者之前对其进行适当的修改(如上所述)。

    事实证明,正如我所料,这会占用大量处理器资源。我的测试内容是来自实时站点的 29K 真实世界 HTML,包含 56 个<a href ...> 和 6 个<link rel ...> 元素,在 1 GHz Opteron 1218 和 43 ms 2.4GHz Xeon E5620 上重写操作需要 128 ms。这些基准严格用于附加操作——不包括实际“代理”功能本身所需的(少量)时间。这个时间成本不是不可克服的,但可能会增加很多 CPU 时间。这比基于正则表达式的内容重写花费的时间要长得多,但它要精确得多,而且不太可能破坏它所触及的页面。

    【讨论】:

      【解决方案2】:

      Nginx 的 HttpSubsModule 非常适合我:http://wiki.nginx.org/HttpSubsModule

      从 http 更改为 https 应该像这样简单:

      location / {
          sub_filter_types text/html text/css text/xml;
          sub_filter http.example.com https.example.com gi;
          sub_filter_once off;
      }
       
      

      默认情况下,仅替换第一个匹配项。设置sub_filter_once off;全部替换。

      【讨论】:

        【解决方案3】:

        完全相同,但语法正确。

        location / {
            sub_filter_types text/html text/css text/xml;
            sub_filter 'http.example.com' 'https.example.com';
        }
        

        【讨论】:

        • 在我的情况下,我必须使用 sub_filter_once off; 否则替换只会在第一次出现时发生。
        • 注意sub_filter_types默认处理text/html,如果你包含它,nginx会警告它是重复的。因此,以下内容就足够了:sub_filter_types text/css text/xml;
        猜你喜欢
        • 1970-01-01
        • 2011-02-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-09-12
        • 2016-06-12
        • 2019-09-06
        相关资源
        最近更新 更多