jco*_*lum 7 amazon-s3 amazon-web-services static-site amazon-cloudfront
有一个叫做 的桶www.foo.site
。在该站点中,有一个登录页面、一个关于页面和一些bar/*
文件夹中的一些页面。每个bar/*
都有一个 index.html 页面:bar/a/index.html、bar/b/index.html 等。
登陆页面运行良好(意味着 www.foo.site 将在我浏览时加载)但是当我点击我的关于链接等时/about/index.html
页面和/bar/index.html
页面没有得到服务。如果curl
我得到 404 的 URL。我'我试过分别设置源路径和源域名:
第一次尝试:
domain name: www.foo.site.s3.amazonaws.com
origin path: (blank)
Run Code Online (Sandbox Code Playgroud)
第二次尝试:
domain name: s3-us-west-1.amazonaws.com
origin path: www.foo.site
Run Code Online (Sandbox Code Playgroud)
两者的默认文档都是 index.html。
没有一个工作。上面提到的所有 S3 页面都可以直接浏览。含义https://s3-us-west-1.amazonaws.com/www.foo.site/bar/index.html加载预期的 html。
这一定是我缺少的一些 Cloudfront 设置。可能是我的 DNS 记录中的某些内容?是否可以通过 Cloudfront 在 S3“文件夹”中提供 html 文件?
这里有一些资源在通过隐式方式从 S3 提供 index.html 时很有帮助,https://domain/folder/
而不必显式使用https://domain/folder/index.html
:
配置 CloudFront 分配时的关键是:
不要为您的 CloudFront 分配配置默认根对象
如果您将 index.html 配置为默认根对象,https://domain/
则将正确提供服务,https://domain/index.html
但不会使用诸如此类的子文件夹引用https://domain/folder/
。
在将 CF 分配连接到 S3 存储桶时,不要使用 Cloudfront 中的下拉菜单也很重要。您需要使用 S3 静态站点的 URL。
您现在可以使用 CloudFront Functions 来执行此操作,而不是使用 Lambda@Edge。正如AWS 新闻博客中所述,使用 CF 函数有很多好处。
您可以使用此 CloudFormation 代码段来部署 S3/CloudFront/Functions 资源。
Resources:
DistributionBucket:
Type: AWS::S3::Bucket
Properties:
BucketEncryption:
ServerSideEncryptionConfiguration:
- ServerSideEncryptionByDefault:
SSEAlgorithm: AES256
BucketName: test-site-site
PublicAccessBlockConfiguration:
BlockPublicAcls: true
BlockPublicPolicy: true
IgnorePublicAcls: true
RestrictPublicBuckets: true
Tags:
- Key: STAGE
Value: dev
UpdateReplacePolicy: Retain
DeletionPolicy: Retain
DistributionBucketPolicy:
Type: AWS::S3::BucketPolicy
Properties:
Bucket: !Ref DistributionBucket
PolicyDocument:
Statement:
- Action: s3:*
Condition:
Bool:
aws:SecureTransport: 'false'
Effect: Deny
Principal:
AWS: "*"
Resource:
- !GetAtt DistributionBucket.Arn
- !Sub '${DistributionBucket.Arn}/*'
- Action: s3:GetObject
Effect: Allow
Principal:
CanonicalUser: !GetAtt DistributionOAI.S3CanonicalUserId
Resource:
- !Sub '${DistributionBucket.Arn}/*'
Version: '2012-10-17'
DistributionCertificate:
Type: AWS::CertificateManager::Certificate
Properties:
DomainName: !Ref DomainName
DomainValidationOptions:
- DomainName: !Ref DomainName
HostedZoneId: !Ref HostedZoneId
Tags:
- Key: STAGE
Value: dev
ValidationMethod: DNS
DistributionOAI:
Type: AWS::CloudFront::CloudFrontOriginAccessIdentity
Properties:
CloudFrontOriginAccessIdentityConfig:
Comment: Identity for s3-origin-test-site
Distribution:
Type: AWS::CloudFront::Distribution
Properties:
DistributionConfig:
Aliases:
- !Ref DomainName
Comment: Distribution for test-site
DefaultCacheBehavior:
AllowedMethods:
- GET
- HEAD
CachePolicyId: 658327ea-f89d-4fab-a63d-7e88639e58f6
Compress: true
FunctionAssociations:
- EventType: viewer-request
FunctionARN: !GetAtt DistributionFunction.FunctionMetadata.FunctionARN
TargetOriginId: s3-origin-test-site
ViewerProtocolPolicy: redirect-to-https
DefaultRootObject: index.html
Enabled: true
HttpVersion: http2
IPV6Enabled: true
Origins:
- DomainName: !GetAtt DistributionBucket.RegionalDomainName
Id: s3-origin-test-site
S3OriginConfig:
OriginAccessIdentity: !Sub 'origin-access-identity/cloudfront/${DistributionOAI}'
PriceClass: PriceClass_200
ViewerCertificate:
AcmCertificateArn:
Ref: DistributionCertificate
MinimumProtocolVersion: TLSv1.2_2021
SslSupportMethod: sni-only
Tags:
- Key: STAGE
Value: dev
DistributionFunction:
Type: AWS::CloudFront::Function
Properties:
AutoPublish: true
FunctionCode: |
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;
}
FunctionConfig:
Comment: Redirect-Default-Index-Request
Runtime: cloudfront-js-1.0
Name: test-site-site-redirect-index-request
DistributionRecordSetA:
Type: AWS::Route53::RecordSet
Properties:
Name: !Sub '${DomainName}.'
Type: A
AliasTarget:
DNSName: !GetAtt Distribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2
Comment: 'Alias record for test-site'
HostedZoneId: !Ref HostedZoneId
DistributionRecordSetAAAA:
Type: AWS::Route53::RecordSet
Properties:
Name: !Sub '${DomainName}.'
Type: AAAA
AliasTarget:
DNSName: !GetAtt Distribution.DomainName
HostedZoneId: Z2FDTNDATAQYW2
Comment: 'Alias record for test-site'
HostedZoneId: !Ref HostedZoneId
Run Code Online (Sandbox Code Playgroud)
提炼@captainblack的优秀答案,您只需将以下CloudFront函数与您的CloudFront发行版的缓存行为的查看者请求相关联即可实现您的目标:
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;
}
Run Code Online (Sandbox Code Playgroud)
这比 @jarmod 的答案中过时的方法要好得多,因为这更容易实现,并且与那些方法不同,它通过 HTTPS 与 CloudFront 兼容。
此方法的另一个好处是,它会隐藏/index.html
浏览器 URL 末尾的丑陋字符串,除非用户键入该字符串。
归档时间: |
|
查看次数: |
4427 次 |
最近记录: |