我有一个S3-bucket,我正在使用CloudFront服务。我想从中提供一些JSON文件。
开箱即用,CF响应根本不包含此文件类型的任何Content-Type
标头。该文件只是由浏览器下载为任何常规文件。但是,我希望它有一个合适的mime类型标题:Content-Type: application/json
。
我知道,我可以在S3中手动为任何单个文件设置自定义标头,但是,是否可以为特定文件扩展名指定一些规则,以便将特定的HTTP标头添加到Amazon CloudFront中的响应中?
答案 0 :(得分:4)
更新:CloudFront本身不提供用于操纵标头的内置机制,但与CloudFront结合使用的Lambda@Edge提供了一种机制来创建可以检查和修改源响应标头的钩子。它实际上无法检查响应体,但可以注入静态或启发式派生的头。如果内容来自已知/可信来源且内容类型已知,但这可能不适用于用户提交的内容,这可能是一种可行的解决方法,因为不正确的内容类型可能会导致浏览器误解有效负载,可能是一个潜在的漏洞利用载体。正确地,在上传对象时,设置内容类型可能仍然是更好的解决方案。
此处的原始答案早于Lambda @ Edge,并且指的是CloudFront本身的本机功能。
CloudFront使用原始服务器提供的响应标头,无论是S3还是自定义源。 CloudFront不提供重写或添加它们的机制。
解决方案是在最初将对象上传到S3时在对象上设置Content-Type
。
如果您将文件上传到设置了Content-Type
的S3,则下载对象时将返回相同的值(无论是直接从S3还是通过CloudFront)。否则,如果您不想要S3指定的默认Content-Type: binary/octet-stream
标题,则必须在上传后修改对象。
答案 1 :(得分:2)
如果您无法控制如何将对象上传到S3存储桶,则可以使用Lambda@Edge函数覆盖响应标头,如下所示:
(此方法的缺点是会增加延迟并产生额外费用)
创建一个IAM策略,该策略将在下一步中附加到lambda函数的角色:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "StatementForCloudWatchLogs",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
},
{
"Sid": "StatementForLambdaFunction",
"Effect": "Allow",
"Action": [
"lambda:EnableReplication",
"lambda:GetFunction"
],
"Resource": [
"arn:aws:lambda:us-east-1:{YOUR_ACCOUNT_ID}:function:{FUNCTION_NAME}:{FUNCTION_VERSION}"
]
},
{
"Sid": "StatementForIAMServiceLinkedRoles",
"Effect": "Allow",
"Action": [
"iam:CreateServiceLinkedRole"
],
"Resource": "arn:aws:iam::{YOUR_ACCOUNT_ID}:role/*"
},
{
"Sid": "StatementForCloudFrontDistributions",
"Effect": "Allow",
"Action": [
"cloudfront:CreateDistribution",
"cloudfront:UpdateDistribution"
],
"Resource": "*"
}
]
}
为lambda创建新的AWS服务IAM角色,并将您在步骤1中创建的策略附加到该角色。在信任关系下,确保您同时拥有这两者; lambda.amazonaws.com
和edgelambda.amazonaws.com
作为可信实体。
创建lambda函数,然后发布新版本(在操作下)。您必须使用nodejs6.10运行时属性创建函数:
'use strict';
exports.handler = (event, context, callback) => {
const response = event.Records[0].cf.response;
if (response.status === '200') {
response.headers['content-type'] = [{
'value': 'application/json', // <-- Your desired content type.
'key': 'Content-Type'
}];
}
callback(null, response);
};
为CloudFront分配中的json文件创建新行为(例如path/to/your/json/*.json
),并确保将其置于Default (*)
行为之上。
arn:aws:lambda:us-east-1:{YOUR_ACCOUNT_ID}:function:{FUNCTION_NAME}:{FUNCTION_VERSION}
。 (注意:您的lambda函数必须在美国东部(弗吉尼亚北部)区域创建,函数ARN必须具有编号版本,而不是$LATEST
或别名。path/to/your/json/*
文件创建CloudFront失效。请务必阅读Requirements and Restrictions on Lambda Functions。
有关其他信息,另请参阅Lambda Event Structure。