我被要求找出如何使Akamai(或任何其他CDN,或NGINX)修改实际响应正文。
为什么?
我需要让CDN将所有“http://”请求更改为“https://”,而不是修改应用程序代码以使用“//”进行外部资源请求。
这可能吗?
有人知道吗?
这似乎可以通过多种不同的方法实现,但这并不意味着实际上做起来是如此明智。它可能存在潜在问题(例如:如果您重写了不应该重写的东西怎么办?)并且需要消耗大量机器资源(需要大量 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 时间。这比基于正则表达式的内容重写要花费更长的时间,但更加精确,并且不太可能破坏所涉及到的页面。
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;
以替换所有内容。
只是一样,但是正确的语法。
location / {
sub_filter_types text/html text/css text/xml;
sub_filter 'http.example.com' 'https.example.com';
}
sub_filter_once off;
,否则替换只会发生在第一次出现。 - Sam Sirrysub_filter_types
默认处理text/html
,如果您包含它,nginx 将会警告它是一个重复项。因此,以下内容已足够:sub_filter_types text/css text/xml;
- Sam Sirry