我正在尝试配置 CloudFront ,以便它根据的值从 S3 或外部来源获取内容。 >标题。
为此,我实现了 Lambda @ Edge ,该事件在 Origin Request 事件中触发。它将来源更改为自定义来源,但是,以某种方式,CloudFront仍仍在访问S3 内容。
这是Lambda函数:
'use strict';
const PRERENDER_HOST = 'xxxxx.ngrok.io'
const IS_SSL = false
exports.handler = (event, context, callback) => {
console.log('event', JSON.stringify(event))
const request = event.Records[0].cf.request;
const headers = request.headers;
const should_prerender = headers['x-should-prerender']
? JSON.parse(headers['x-should-prerender'][0].value)
: false
console.log('should prerender', should_prerender, 'existed', !!headers['x-should-prerender'])
console.log('uri is', request.uri)
if (should_prerender) {
set_header('host', PRERENDER_HOST, headers)
request.origin = {
custom: {
domainName: PRERENDER_HOST,
port: IS_SSL ? 443 : 80,
protocol: IS_SSL ? 'https' : 'http',
readTimeout: 20,
keepaliveTimeout: 5,
customHeaders: {},
path: request.uri,
sslProtocols: ['TLSv1', 'TLSv1.1'],
}
}
}
console.log('request', JSON.stringify(request))
callback(null, request)
function set_header(name, value, store) {
store[name.toLowerCase()] = [
{
key: name,
value
}
]
}
};
接下来,我将粘贴传递到request
的{{1}}的内容。这已从相关的CloudWatch日志中提取。日志显示了如何建立自定义来源。
callback
有什么想法在这里发生吗?
更新1 :尝试使用{
"uri" : "/index.html",
"origin" : {
"custom" : {
"sslProtocols" : [
"TLSv1",
"TLSv1.1"
],
"keepaliveTimeout" : 5,
"port" : 80,
"domainName" : "xxxxx.ngrok.io",
"path" : "/index.html",
"customHeaders" : {},
"readTimeout" : 20,
"protocol" : "http"
}
},
"headers" : {
"x-should-prerender" : [
{
"key" : "x-should-prerender",
"value" : "true"
}
],
"host" : [
{
"key" : "host",
"value" : "xxxxx.ngrok.io"
}
],
"upgrade-insecure-requests" : [
{
"value" : "1",
"key" : "Upgrade-Insecure-Requests"
}
],
"dnt" : [
{
"key" : "DNT",
"value" : "1"
}
],
"x-forwarded-for" : [
{
"key" : "X-Forwarded-For",
"value" : "xxx.xxx.xx.xx"
}
],
"via" : [
{
"value" : "1.1 25xxxxxbcxxxx07847a7xxxxxx.cloudfront.net (CloudFront)",
"key" : "Via"
}
],
"user-agent" : [
{
"key" : "User-Agent",
"value" : "Amazon CloudFront"
}
],
"accept-encoding" : [
{
"key" : "Accept-Encoding",
"value" : "gzip"
}
]
},
"clientIp" : "xxx.xx.xx.xxx",
"querystring" : "",
"method" : "GET"
}
后,一切正常。不过,不知道为什么它不能与https
一起使用。
更新2 :更正一个错误。我写了View Request而不是Origin Request。感谢Michael的注意。
答案 0 :(得分:1)
查看器请求触发器在CloudFront的“前端”(查看器端)运行,这在缓存检查之前。
在这一点上原点是“已知的”,因为已经进行了“缓存行为”匹配,但是您无法在查看器端影响原点选择,因为CloudFront尚未从技术上决定是否联系原点。
只能在CloudFront的Origin Request触发器中在CloudFront的原始端(缓存检查后,在背面)上进行对原始服务器的更改。查看者请求触发器更改原点是没有意义的,因为原点不是缓存键的一部分,因此,如果查看者请求触发器更改了原点,则将检查缓存而不会为缓存做任何调整。更改了原点,因此无法保证缓存的响应甚至来自正确的位置。
您将需要使用“原始请求”触发器,并且需要将x-should-prerender
列入白名单以转发到原始位置(在“缓存行为”设置中),以便触发器可以看到它。如果您不希望原产地实际看到它,则需要使用触发代码将其删除,但是必须将其列入白名单,以使原产地请求触发器能够看到它。
如果您希望函数以一种影响原始响应的方式更改请求,请使用原始请求事件。