我正在尝试为通过路由 53 购买的域设置别名。该别名将指向我网站中具有如下 URL 的页面:
http://example.com/website/:id
我的 api 使用以下参数设置托管区域:
var params = {
CallerReference: req.body.projectId,
Name: req.body.domain,
HostedZoneConfig: {
Comment: `the zone created on ${today} for ${req.body.domain}`,
PrivateZone: false
}
};
在下一步中,我将使用以下参数设置 DNS 记录:
var params = {
ChangeBatch: {
Changes: [
{
Action: "CREATE",
ResourceRecordSet: {
AliasTarget: {
DNSName: `http://example.com/website/${req.body.projectId}`,
EvaluateTargetHealth: false,
HostedZoneId: hostedZone.HostedZone.Id
},
Name: "example.com",
Type: "A"
}
}
],
},
HostedZoneId: hostedZone.HostedZone.Id
};
我收到一条错误消息,指出我的别名目标名称不在目标区域内。我缺少哪个步骤来正确设置它?
最佳答案
DNS 没有处理路径的机制,因此这里尝试的操作在 DNS 中是不可能的。但这似乎是为了解决不同的问题。
Is there a way to route to a generic s3 bucket instead of a bucket with a matching name?
不……是的。
S3 依赖于浏览器认为主机名应该是什么(如传入的 Host
header 所示),以便将请求发送到正确的存储桶。
因此,当 S3 单独使用时,如果 DNS 条目指向某个存储桶,则该存储桶名称必须与主机名完全匹配。
对于不同的行为,例如http://bucket.example.com
指向名为example-bucket
的存储桶,您需要一个反向代理来处理 header 重写这样,当浏览器指定 Host:bucket.example.com
时,S3 会收到带有 Host:example-bucket.s3.amazonaws.com
的请求。
CloudFront 提供了这样的反向代理功能。
配置 CloudFront 分配时,您可以指定源域名(指向存储桶)和备用域名,后者指定您希望 CloudFront 从浏览器获得的内容。 CloudFront 会在运行中重写请求,以便 S3 看到的内容与浏览器发送的内容不同。
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/MigrateS3ToCloudFront.html
正如该页所述,S3 和 CloudFront 的定价结构使得单独使用 S3 或 S3 + CloudFront 之间的成本差异实际上可以是任意一种——实际上,同时使用两者的成本会稍微低一些,具体取决于存储桶位置、查看器位置、对象大小和缓存命中率(假设您没有禁用 CloudFront 缓存)。
如果您希望从根路径为 website/1 的
你也可以这样做,但是有点棘手。example-bucket
提供 https://website-1.example.com
/
您可以通过在 CloudFront 中的源配置上设置源路径来一次性静态地执行此操作,因为该字段表示路径前缀,在每个请求发送到源之前,该路径前缀将添加到每个请求上。
或者您可以使用 CloudFront 和 Lambda@Edge 触发器动态修改它。看起来可能是这样的。
'use strict';
// if the end of incoming Host header matches this string,
// strip this part and prepend the remaining characters onto the request path,
// along with a new leading slash (otherwise, the request will be handled
// with an unmodified path, at the root of the bucket)
const remove_suffix = '.example.com';
// provide the correct origin hostname here so that we send the correct
// Host header to the S3 website endpoint
const origin_hostname = 'example-bucket.s3-website-us-east-1.amazonaws.com';
exports.handler = (event, context, callback) => {
const request = event.Records[0].cf.request;
const headers = request.headers;
const host_header = headers.host[0].value;
if(host_header.endsWith(remove_suffix))
{
// prepend '/' + the subdomain onto the existing request path ("uri")
request.uri = '/' + host_header.substring(0,host_header.length - remove_suffix.length) + request.uri;
}
// fix the host header so that S3 understands the request
headers.host[0].value = origin_hostname;
// return control to CloudFront with the modified request
return callback(null,request);
};
上面是我编写并发布在 the official AWS forum 上的示例。它仅适用于 S3 网站托管功能(不适用于 REST 端点),因为这是使用转发 header 白名单将主机 header 公开给 Lambda@Edge 所必需的。
它从传入主机名中获取前缀并将其重写为路径前缀,同时将所有请求发送到同一个存储桶。
请注意,您将需要 Origin Response 触发器中的补充功能来处理响应、检查 HTTP 30x 重定向。由于我们正在执行路径前缀,因此需要在反向路径上执行相反的操作,以便正确锚定 Location
header 的路径。
或者只是为每个站点创建一个 CloudFront 分配 - AWS 不会对分配本身收费,仅对其处理的请求收费。可以通过自动化轻松创建发行版——使用 aws-cli 或 CloudFormation 编写脚本。每个账户的 CloudFront 分配的默认限制为 200,但 AWS Support 将根据请求增加此限制。
关于amazon-web-services - Route 53 别名 DNS 记录 : the alias target name does not lie within the target zone,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49472636/