修改HTML响应(不是头部)

22
希望有人可以帮我或指导我。
我被要求找出如何使Akamai(或任何其他CDN,或NGINX)修改实际响应正文。
为什么?
我需要让CDN将所有“http://”请求更改为“https://”,而不是修改应用程序代码以使用“//”进行外部资源请求。
这可能吗?
有人知道吗?
3个回答

16

这似乎可以通过多种不同的方法实现,但这并不意味着实际上做起来是如此明智。它可能存在潜在问题(例如:如果您重写了不应该重写的东西怎么办?)并且需要消耗大量机器资源(需要大量 CPU 循环来解析和修改响应主体)。

Nginx 有 http_sub_module,看起来可以以相对简单的方式完成此操作,假设您想要替换的内容很简单,并且每个页面只需要匹配一个模式,例如将 <a href="http://example.com/... 替换为 <a href="https://example.com/...,可以多次进行。这种内容修改似乎有些可疑,但根据您所处的情况(可能是应用程序受到限制),这可能会帮助您实现目标。

貌似还有一种叫做 http_substitutions_filter 的方法,这可能是非官方的或至少不是 Nginx 核心发行版的一部分,可以对响应主体进行更强大的基于过滤器的重写。

Varnish 似乎有 类似的功能(可能是插件),但 HAProxy 没有,因为它只处理头部,并且除了进行 gzip 卸载时,会忽略主体。其他相反代理软件如 Apache 或 Squid 也可能提供一些有用的功能,您可以将它们放在应用程序服务器前面。

我的初步印象是,仅仅进行简单的字符串替换可能无法达到预期效果,即使使用基于正则表达式的替换也不足以胜任,除非正则表达式非常复杂,因为这样做很容易改写不该改写的内容。

我建议为了最正确地实现这一目的,应该使用 DOM 解析库来解释生成的 HTML,遍历整个树状结构,并直接修改相关元素,然后将修改后的文档交给请求方。这样,文档就可以基于上下文理解其内容进行修改。

在我看来,这听起来有些复杂,因为它确实是复杂的,所以我再次建议你重新考虑你计划采用的方法,除非这超出你的控制范围。

最后想说的是:好奇心促使我将此问题与我为另一个目的编写的 http 反向代理(根据内容类型)进行了适配,以便能够实际解析和遍历 HTML 结构,并在返回响应正文之前直接对其进行修改(如上所述)。

结果与我预期的一样,这需要相当多的处理器资源。我的测试内容是来自实际站点的 29K HTML,其中包含了 56 个 <a href ...> 和 6 个 <link rel ...> 元素,重写操作在 1 GHz Opteron 1218 上需要 128 毫秒,在 2.4GHz Xeon E5620 上需要 43 毫秒。这些基准测试仅涉及额外的操作,不包括实际“代理”功能所需的(较小量的)时间。这个时间成本并非无法克服,但可能会消耗大量的 CPU 时间。这比基于正则表达式的内容重写要花费更长的时间,但更加精确,并且不太可能破坏所涉及到的页面。


15

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;以替换所有内容。


9

只是一样,但是正确的语法。

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

参考:http://nginx.org/en/docs/http/ngx_http_sub_module.html#sub_filter - Sam Sirry
1
在我的情况下,我必须使用 sub_filter_once off;,否则替换只会发生在第一次出现。 - Sam Sirry
请注意,sub_filter_types 默认处理 text/html,如果您包含它,nginx 将会警告它是一个重复项。因此,以下内容已足够:sub_filter_types text/css text/xml; - Sam Sirry

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接