Cloudfront URL重写/重新映射,因此内容有两个URL?

时间:2018-03-04 22:26:40

标签: amazon-s3 aws-lambda amazon-cloudfront

我正在管理一个文档网站,其中包含此格式的网址:

/product-foo/1.2.3/user-guide/system-requirements.html

我希望网页上有两个网址:

/product-foo/1.2.3/user-guide/system-requirements.html  
/product-foo/latest/user-guide/system-requirements.html

可以使用如本章所述的Apache Web服务器来完成 http://httpd.apache.org/docs/2.4/rewrite/remapping.html

  

“假设我们最近将页面foo.html重命名为bar.html,现在想要提供旧URL以实现向后兼容。但是,我们希望旧网址的用户甚至不会识别这些网页被重命名 - 也就是说,我们不希望在浏览器中更改地址   解决方案:我们通过以下规则在内部将旧网址重写为新网址:
      RewriteEngine on
      RewriteRule "^/foo\.html$" "/bar.html" [PT]"

我们的想法是,对于每个新产品版本,我都会更新重定向,以便将“最新”模式指向最新发布版本的文档。这样人们可以根据需要链接到最新的文档,也可以根据需要链接到特定版本的版本。

可以使用Cloudfront 配置完成吗?没有Cloudfront,可以单独使用s3吗?可以使用AWS Lambda或Lambda @ Edge吗? (解决方案是否受限于Lambda @ Edge带限制?)您能提供具体的示例解决方案吗?

2 个答案:

答案 0 :(得分:4)

这可以使用Lambda @ Edge触发器完成。生成的Lambda @ Edge响应大小限制不适用,除非Lambda函数本身通过使用已创建的内容填充响应对象的body属性来实际生成响应。在其他地方获得,因此在函数内生成响应。

使用Origin Request触发器:

  • 触发器仅在检查缓存后触发,并且仅当缓存命中时(缓存命中,未联系原点,因此不需要调用触发器)
  • 触发器在请求发送到原始文件之前触发
  • 您可以修改将在请求中发送到原始
  • 的路径
  • 响应缓存在浏览器最初请求的路径下,而不是修改后的路径
  • 浏览器未重定向,因此地址栏不会更改.¹

从根本上说,我们在Lambda函数中需要做的就是提取请求对象,修改URI²并告诉CloudFront继续处理请求,并进行修改。我们只是在飞行中重写部分请求,并将控制权返回给CloudFront。

下面的示例几乎肯定不是处理一系列可能的字符串操作的最佳或最整洁的方法,但足以说明您的代码需要完成的一般概念,通过任何映射和匹配机制想用。

您可以静态重新映射值,或者您可以使用任意数量的数据库策略来查找原始路径并找到要使用的正确的当前目标。

'use strict';

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;

    request.uri = request.uri
        .replace(/^\/product-foo\/latest\//,'/product-foo/1.0.0/')
        .replace(/^\/product-bar\/latest\//,'/product-bar/3.2.1/')
        .replace(/^\/product-three\/latest\//,'/product-three/5.5.5/');

    return callback(null, request);
};

event.Records始终是一个只包含一个成员的数组,event.Records[0].cf包含此特定调用的所有相关信息。 event.Records[0].cf.request是原始请求。修改此对象并将其作为第二个参数提供给回调,指示CloudFront使用修改后的请求继续正常处理。

回调的第一个参数始终是null,表示没有发生异常。如果抛出异常,或者第一个参数不是null,则CloudFront会向查看器返回一般错误...它不会显示异常,因为它可能包含堆栈跟踪或其他敏感信息不应该暴露。可以在Lambda日志中访问该错误。

当然,原始服务器实际上是通过重定向来响应的。

²兰德尔@Edge调用“URI”实际上只是路径。完整的URI在技术上是路径+'' +查询字符串,但Lambda @ Edge将这两件事分开。

答案 1 :(得分:0)

你可以通过很多方式实现这一目标。

您可以使用新名称指向s3存储桶中的对象。

使用cloudfront中的模式,如果没有与您的模式匹配,您可以使用API​​网关将其发送到lambda,您可以使用重定向配置新文件的位置。您可以将错误路径作为lambda的路径参数接收。您可以在s3位置或发电机或任何所需存储中维护配置。

希望它有所帮助。