使用 AWS Lambda@Edge 删除内容长度
Remove Content-Length using AWS Lambda@Edge
我通过 AWS CloudFormation 模板进行了以下 CloudFront 设置:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
DependsOn:
- LoggingBucket
- LambdaEdgeFunction
Properties:
DistributionConfig:
Comment: 'Route to multiple origins with CloudFront'
Enabled: true
IPV6Enabled: !Ref 'IPV6Enabled'
Logging:
Bucket: !Sub '${LoggingBucket}.s3.amazonaws.com'
HttpVersion: http2
Comment: !Join [ '', [!Ref 'AWS::StackName', ' Cloud Front']]
Aliases:
- !Ref 'AlternateDomainNames'
ViewerCertificate:
AcmCertificateArn: !Ref ACMCertificateArn
SslSupportMethod: !Ref 'SslSupportMethod' #sni-only
MinimumProtocolVersion: !Ref 'MinimumProtocolVersion' #TLSv1.1_2016
Origins:
- Id: APIGOrigin
DomainName: !Sub ${ApiGatewayId}.execute-api.eu-west-1.amazonaws.com
OriginPath: !Sub /${ApiStage}
CustomOriginConfig:
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginCustomHeaders:
- HeaderName: 'X-From-CDN'
HeaderValue: !Ref VerifyFromCfHeaderVal
DefaultCacheBehavior:
AllowedMethods: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
CachedMethods: ["GET", "HEAD", "OPTIONS"]
ForwardedValues:
Headers:
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Origin
- Authorization
- Accept
# - Host APIG needs to use SNI
QueryString: !Ref 'QueryString'
Cookies:
Forward: !Ref 'ForwardCookies'
TargetOriginId: APIGOrigin
ViewerProtocolPolicy: https-only
Compress: !Ref 'Compress'
DefaultTTL: !Ref 'DefaultTTL'
MaxTTL: !Ref 'MaxTTL'
MinTTL: !Ref 'MinTTL'
SmoothStreaming: 'false'
# Lambda
LambdaFunctionAssociations:
- EventType: !Ref 'LambdaEventType'
LambdaFunctionARN: !Ref 'LambdaEdgeVersion'
CustomErrorResponses:
- ErrorCachingMinTTL: 0
ErrorCode: 400
- ErrorCachingMinTTL: 1
ErrorCode: 403
- ErrorCachingMinTTL: 5
ErrorCode: 500
所以每次 API 网关源响应时,它都会触发 Lambda@Edge,目前我有:
# LAMBDA@EDGE FUNCTION
LambdaEdgeFunction:
Type: 'AWS::Lambda::Function'
Properties:
Description: !Sub 'A custom Lambda@Edge function for serving custom headers from CloudFront Distribution'
FunctionName: !Sub '${AppName}-lambda-edge-${Environment}'
Handler: index.handler
Role: !GetAtt 'LambdaEdgeIAMRole.Arn'
MemorySize: 128
Timeout: 5
Code:
ZipFile: !Sub |
'use strict';
exports.handler = (event, context, callback) => {
console.log('Adding additional headers to CloudFront response.');
const response = event.Records[0].cf.response;
console.log("Response received:\n", JSON.stringify(response));
response.headers['strict-transport-security'] = [{
key: 'Strict-Transport-Security',
value: 'max-age=86400; includeSubdomains; preload',
}];
response.headers['x-content-type-options'] = [{
key: 'X-Content-Type-Options',
value: 'nosniff',
}];
response.headers['x-frame-options'] = [{
key: 'X-Frame-Options',
value: "DENY"
}];
response.headers['content-security-policy'] = [{
key: 'Content-Security-Policy',
value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"
}];
response.headers['x-xss-protection'] = [{
key: 'X-XSS-Protection',
value: "1; mode=block"
}];
response.headers['referrer-policy'] = [{
key: 'Referrer-Policy',
value: "same-origin"
}];
console.log('Remove Content-Length headers from CloudFront response..');
delete response.headers["Content-Length"]
callback(null, response);
};
Runtime: nodejs12.x
当我向端点发送请求时,我仍然可以在响应中看到 Content-Length
:
curl -i --http1.1 \
--url https://cdn.domain.tld/s/94163e58494
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Content-Length: 316
Connection: keep-alive
Server: CloudFront
Date: Thu, 30 Apr 2020 17:54:54 GMT
Referrer-Policy: same-origin
X-Frame-Options: DENY
x-amz-apigw-id: Lz-VPFnLDoEFbig=
Cache-Control: max-age=0, no-cache, private
Location: http://google.com
Via: 1.1 15c672a1a9***.cloudfront.net (CloudFront), 1.1 0b7c0b1558a4*****.cloudfront.net (CloudFront)
Strict-Transport-Security: max-age=86400; includeSubdomains; preload
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'
X-XSS-Protection: 1; mode=block
x-amzn-RequestId: 0a29a0a9-c14f-4c14-b773-d57813cf91c3
X-Amzn-Trace-Id: Root=1-5eab10ee-50d2c5e08498c8689ad025e0;Sampled=0
X-Amz-Cf-Pop: LHR52-C1
X-Cache: Miss from cloudfront
X-Amz-Cf-Pop: LHR52-C1
X-Amz-Cf-Id: c1KMNm2DOHzfzsIYLBeShWVlxVyaN8yO33hZ3aAAjVIR03x2gx49sw==
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="refresh" content="0;url='http://google.com'" />
<title>Redirecting to http://google.com</title>
</head>
<body>
Redirecting to <a href="http://google.com">http://google.com</a>.
</body>
</html>
我已遵循 https://aws.amazon.com/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/ 指南,但我仍然无法看到如何从响应中删除 Content-Length
- 这可能吗?
非常感谢任何建议
什么是 LambdaEventType
?编辑 CloudFront 的响应应该是 viewer-response
。
您的函数应该删除 content-length
而不是 Content-Length
,因为 header 名称在 headers 数组中应该是小写的。
delete response.headers["content-length"]
The keys in the headers object are lowercase versions of standard HTTP header names. Using lowercase keys gives you case-insensitive access to the header values.
您似乎无法修改 read-only header,因为您收到此错误:
The Lambda function result failed validation: The function tried to add, delete, or change a read-only header.
我通过 AWS CloudFormation 模板进行了以下 CloudFront 设置:
CloudFrontDistribution:
Type: AWS::CloudFront::Distribution
DependsOn:
- LoggingBucket
- LambdaEdgeFunction
Properties:
DistributionConfig:
Comment: 'Route to multiple origins with CloudFront'
Enabled: true
IPV6Enabled: !Ref 'IPV6Enabled'
Logging:
Bucket: !Sub '${LoggingBucket}.s3.amazonaws.com'
HttpVersion: http2
Comment: !Join [ '', [!Ref 'AWS::StackName', ' Cloud Front']]
Aliases:
- !Ref 'AlternateDomainNames'
ViewerCertificate:
AcmCertificateArn: !Ref ACMCertificateArn
SslSupportMethod: !Ref 'SslSupportMethod' #sni-only
MinimumProtocolVersion: !Ref 'MinimumProtocolVersion' #TLSv1.1_2016
Origins:
- Id: APIGOrigin
DomainName: !Sub ${ApiGatewayId}.execute-api.eu-west-1.amazonaws.com
OriginPath: !Sub /${ApiStage}
CustomOriginConfig:
HTTPSPort: 443
OriginProtocolPolicy: https-only
OriginCustomHeaders:
- HeaderName: 'X-From-CDN'
HeaderValue: !Ref VerifyFromCfHeaderVal
DefaultCacheBehavior:
AllowedMethods: ["DELETE", "GET", "HEAD", "OPTIONS", "PATCH", "POST", "PUT"]
CachedMethods: ["GET", "HEAD", "OPTIONS"]
ForwardedValues:
Headers:
- Access-Control-Request-Headers
- Access-Control-Request-Method
- Origin
- Authorization
- Accept
# - Host APIG needs to use SNI
QueryString: !Ref 'QueryString'
Cookies:
Forward: !Ref 'ForwardCookies'
TargetOriginId: APIGOrigin
ViewerProtocolPolicy: https-only
Compress: !Ref 'Compress'
DefaultTTL: !Ref 'DefaultTTL'
MaxTTL: !Ref 'MaxTTL'
MinTTL: !Ref 'MinTTL'
SmoothStreaming: 'false'
# Lambda
LambdaFunctionAssociations:
- EventType: !Ref 'LambdaEventType'
LambdaFunctionARN: !Ref 'LambdaEdgeVersion'
CustomErrorResponses:
- ErrorCachingMinTTL: 0
ErrorCode: 400
- ErrorCachingMinTTL: 1
ErrorCode: 403
- ErrorCachingMinTTL: 5
ErrorCode: 500
所以每次 API 网关源响应时,它都会触发 Lambda@Edge,目前我有:
# LAMBDA@EDGE FUNCTION
LambdaEdgeFunction:
Type: 'AWS::Lambda::Function'
Properties:
Description: !Sub 'A custom Lambda@Edge function for serving custom headers from CloudFront Distribution'
FunctionName: !Sub '${AppName}-lambda-edge-${Environment}'
Handler: index.handler
Role: !GetAtt 'LambdaEdgeIAMRole.Arn'
MemorySize: 128
Timeout: 5
Code:
ZipFile: !Sub |
'use strict';
exports.handler = (event, context, callback) => {
console.log('Adding additional headers to CloudFront response.');
const response = event.Records[0].cf.response;
console.log("Response received:\n", JSON.stringify(response));
response.headers['strict-transport-security'] = [{
key: 'Strict-Transport-Security',
value: 'max-age=86400; includeSubdomains; preload',
}];
response.headers['x-content-type-options'] = [{
key: 'X-Content-Type-Options',
value: 'nosniff',
}];
response.headers['x-frame-options'] = [{
key: 'X-Frame-Options',
value: "DENY"
}];
response.headers['content-security-policy'] = [{
key: 'Content-Security-Policy',
value: "default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'"
}];
response.headers['x-xss-protection'] = [{
key: 'X-XSS-Protection',
value: "1; mode=block"
}];
response.headers['referrer-policy'] = [{
key: 'Referrer-Policy',
value: "same-origin"
}];
console.log('Remove Content-Length headers from CloudFront response..');
delete response.headers["Content-Length"]
callback(null, response);
};
Runtime: nodejs12.x
当我向端点发送请求时,我仍然可以在响应中看到 Content-Length
:
curl -i --http1.1 \
--url https://cdn.domain.tld/s/94163e58494
HTTP/1.1 301 Moved Permanently
Content-Type: text/html; charset=UTF-8
Content-Length: 316
Connection: keep-alive
Server: CloudFront
Date: Thu, 30 Apr 2020 17:54:54 GMT
Referrer-Policy: same-origin
X-Frame-Options: DENY
x-amz-apigw-id: Lz-VPFnLDoEFbig=
Cache-Control: max-age=0, no-cache, private
Location: http://google.com
Via: 1.1 15c672a1a9***.cloudfront.net (CloudFront), 1.1 0b7c0b1558a4*****.cloudfront.net (CloudFront)
Strict-Transport-Security: max-age=86400; includeSubdomains; preload
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'none'; img-src 'self'; script-src 'self'; style-src 'self'; object-src 'none'
X-XSS-Protection: 1; mode=block
x-amzn-RequestId: 0a29a0a9-c14f-4c14-b773-d57813cf91c3
X-Amzn-Trace-Id: Root=1-5eab10ee-50d2c5e08498c8689ad025e0;Sampled=0
X-Amz-Cf-Pop: LHR52-C1
X-Cache: Miss from cloudfront
X-Amz-Cf-Pop: LHR52-C1
X-Amz-Cf-Id: c1KMNm2DOHzfzsIYLBeShWVlxVyaN8yO33hZ3aAAjVIR03x2gx49sw==
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta http-equiv="refresh" content="0;url='http://google.com'" />
<title>Redirecting to http://google.com</title>
</head>
<body>
Redirecting to <a href="http://google.com">http://google.com</a>.
</body>
</html>
我已遵循 https://aws.amazon.com/blogs/networking-and-content-delivery/adding-http-security-headers-using-lambdaedge-and-amazon-cloudfront/ 指南,但我仍然无法看到如何从响应中删除 Content-Length
- 这可能吗?
非常感谢任何建议
什么是 LambdaEventType
?编辑 CloudFront 的响应应该是 viewer-response
。
您的函数应该删除 content-length
而不是 Content-Length
,因为 header 名称在 headers 数组中应该是小写的。
delete response.headers["content-length"]
The keys in the headers object are lowercase versions of standard HTTP header names. Using lowercase keys gives you case-insensitive access to the header values.
您似乎无法修改 read-only header,因为您收到此错误:
The Lambda function result failed validation: The function tried to add, delete, or change a read-only header.