服务索引文件,而不是下载提示

时间:2019-01-12 21:41:44

标签: html amazon-web-services amazon-s3 aws-lambda amazon-cloudfront

我的网站托管在S3上,并且CloudFront作为CDN,并且我需要这两个URL表现相同并在目录中提供index.html文件:

example.com/directory example.com/directory/

在末尾带有/的那个错误地提示浏览器下载一个零字节的文件,该文件的文件名带有随机散列。没有斜线,它将返回我的404页面。

如何获取两个路径以在目录中传递index.html文件?

如果我有办法“做到”,那就太好了!这就是我所希望的,但是如果没有,我可能会尝试使用Lambda @ Edge进行重定向。无论如何,我还是需要其他一些情况,因此一些有关如何从Lambda @ Edge进行301或302重定向的说明也将有所帮助:)

更新(根据John Hanley的评论)

curl -i https://www.example.com/directory/

HTTP/2 200 
content-type: application/x-directory
content-length: 0
date: Sat, 12 Jan 2019 22:07:47 GMT
last-modified: Wed, 31 Jan 2018 00:44:16 GMT
etag: "[id]"
accept-ranges: bytes
server: AmazonS3
x-cache: Miss from cloudfront
via: 1.1 [id].cloudfront.net (CloudFront)
x-amz-cf-id: [id]

更新

CloudFront设置了一个行为,将http转发到https并将请求发送到S3。在“错误”标签下,它还有404错误路由。

4 个答案:

答案 0 :(得分:1)

这种行为通常由您的HTTP标头数据(特别是您的客户端收到的Content-Type)控制/引起。

Inspect the header,然后尝试调整从服务器返回的内容。那应该导致您的解决方案。

  
      
  1. 在Chrome中,访问URL,右键单击,选择“检查”以打开开发人员工具。
  2.   
  3. 选择“网络”标签。
  4.   
  5. 重新加载页面,在左侧面板上选择任何HTTP请求,HTTP标头将显示在右侧面板上。
  6.   

答案 1 :(得分:1)

S3仅在启用并使用存储桶的网站托管功能时,通过指向存储桶的网站托管端点${bucket}.s3-website.${region}.amazonaws.com而非存储桶的通用REST端点,来提供自动索引文档, ${bucket}.s3.amazonaws.com

网站端点和REST端点具有numerous differences,包括该端点。

看到以/结尾的对象密钥的这些0字节文件的原因是因为您正在使用S3控制台或实际创建0字节对象的另一个实用程序在存储桶中创建文件夹对象。一旦文件夹中包含对象,就不需要它们了-但是它们是在S3控制台中显示空文件夹的唯一方法,该控制台将名为foo/的对象显示为名为{{ 1}},即使没有其他关键字前缀为foo的对象也是如此。这是控制台中文件夹层次结构的可视化仿真的一部分,即使S3中的对象从不真正位于文件夹中。

如果由于某种原因需要使用REST端点(例如,不想将存储桶公开),则需要在CloudFront中使用两个Lambda @ Edge触发器,以相当接近地模拟此功能。

>

原始请求触发器可以在检查CloudFront缓存之后,将请求发送到源之前检查和修改请求。我们使用它来检查以foo/结尾的路径,并在找到后附加/

原始响应触发器可以在将响应写入到CloudFront缓存之前检查并可能修改响应。原始响应触发器还可以检查在生成响应的请求之前的原始请求。我们使用它来检查响应是否为错误。如果是这样,并且原始请求似乎不是不是,则是针对索引文档或文件(具体来说,路径中的最后斜杠后,“文件”至少应包含一个字符,然后是一个点,再加上至少一个字符-如果是,则可能是“文件”)。如果这些都不是,那么我们将重定向到原始路径以及最后添加的index.html

“起源请求和起源响应”触发器仅在缓存未命中时触发。发生缓存命中时,不会触发任何触发器,因为它们位于CloudFront的原始端(缓存的背面)。可以从缓存提供服务的请求从缓存提供服务,因此不会调用触发器。

以下是用Node.js 8.10编写的Lambda @ Edge函数。这个Lambda函数修改其行为,以便根据上下文将其作为源请求或源响应。在Lambda中发布版本后,将该版本的ARN与CloudFront缓存行为设置相关联,两者是“原始请求”和“原始响应”触发器。

/

答案 2 :(得分:0)

给出的答案是错误的。 Cloudfront具有自己的配置,以使www.yourdomain.com/提供文档。它称为“默认根对象”,其配置位于您的Cloudfront发行版的“常规”标签下。这是获取启用了SSL / https的自定义域+ cloudfront + s3存储桶的完整步骤。

  1. 创建一个具有默认(关闭)权限的全新S3存储桶,或从目标存储桶中删除所有公共访问权限。
  2. 禁用静态网站托管。您不需要它。
  3. 如果尚未将SSL证书带入Amazon,则可以将其附加到将指向S3存储桶的cloudfront发行版中。
  4. 使用证书创建指向目标S3存储桶的Cloudfront分发。
  5. 对于来源配置,请使用www.yourdomain.com.s3.amazonaws.com表格作为来源,而不是使用静态网站托管网址(始终应禁用)。
  6. 让cloudfront配置自动更改S3存储桶访问权限(“限制存储桶访问权限”)。您只想(通过特定身份)访问仅限于此Cloudfront发行版的存储桶。没有人应该直接打您的S3存储桶,尤其是因为它可以通过http服务(没有“ s”)。
  7. 在Cloudfront的“常规”标签下(或在安装过程中),将默认的根对象设置为“ index.html”或其他。否则,对https://www.yourdomain.com/的请求将显示拒绝权限。

答案 3 :(得分:0)

最近,AWS 最近推出了可用于此用例的 CloudFront Functions。 与 Lambda@Edge 相比,CloudFront 函数更便宜、更快、更容易实施和测试

下面是一个示例函数,如果在访问路径时未提供 index.html,它会将 index.html 附加到请求中。

function handler(event) {
    var request = event.request;
    var uri = request.uri;
    
    // Check whether the URI is missing a file name.
    if (uri.endsWith('/')) {
        request.uri += 'index.html';
    } 
    // Check whether the URI is missing a file extension.
    else if (!uri.includes('.')) {
        request.uri += '/index.html';
    }

    return request;
}

这不会在 Web 浏览器地址栏中附加 index.html,从而在浏览时提供更清晰的 URL。在您的情况下,https://www.example.com/directory/ 将在浏览时保持原样,但会呈现 https://www.example.com/directory/index.html 的内容。

可以在https://github.com/aws-samples/amazon-cloudfront-functions/blob/main/url-rewrite-single-page-apps/index.js

中找到更多示例