javascript - 如何检查小写 URL 并重定向它们是否对 Lambda@Edge 有效
问题描述
我有一些旧的 URL 过去使用大写字母来表示人名等,但现在我已经将我的网站更新为每个页面的 URL 中的小写字符。所以,如果人们碰巧点击了旧链接,或者不小心输入了大写字母,我想重定向他们。
我还检查删除尾部斜杠。这是我目前在前端使用的代码。我希望切换到使用 Lambda@Edge(我的网站在 S3 上并通过 CloudFront 分发)进行检查和重定向。
这是我在前端使用的 JS 函数:
var newUrl = window.location.href.toLowerCase().replace(/\/$/, '')
loadIfChanged(newUrl)
function loadIfChanged (newUrl) {
if (newUrl != location.href) {
fetch(newUrl, {method: 'HEAD'}).then(function (response) {
if (response.status === 200) return window.location = newUrl
}).catch(function (error) {
return console.log(error)
})
}
}
我如何在 Lambda@Edge 函数中编写它?
也许是这样的:
exports.handler = async function (event, context) {
// Lowercase the URL and trim off a trailing slash if there is one
var path = event.Records[0].cf.request.uri.toLowerCase().replace(/\/$/, '')
// How to do a fetch here? var ok = fetch()
if (ok) {
const response = {
status: '301',
statusDescription: 'Moved Permanently',
headers: {
location: [{
key: 'Location',
value: `https://example.com/${path}`,
}],
},
}
return response
} else {
return event.Records[0].cf.request
}
}
Lambda@Edge 函数甚至可以进行 I/O 吗?
而且,重要的是,这个 Lambda@Edge 函数只能在 404 上运行吗?
解决方案
你写的应该可以工作,但我认为更好的实现是简单地更改OriginRequest Lambda 函数中的 URI。代码很简单:
import json
def lambda_handler(event, context):
request = event['Records'][0]['cf']['request'];
request['uri'] = "anything";
return request;
这里要注意的一个有趣的细节是,CF 将根据原始 URI 缓存修改后的 URI 的结果。因此,如果再次请求原始 URI,CloudFront 将直接从缓存中返回响应。
为什么是原始请求?
- 因为它仅在缓存未命中时触发
- 它有助于获得上述缓存的好处
为什么这种方式比你提出的更好?
如果您决定采用上述方法,以下是请求流程:
对于非缓存内容:
User -> CF -> Lambda -> S3 -> Final response to the user
对于缓存的内容:
User -> CF -> Final response to the user
而如果您使用 Lambda 生成 301,则流程将是:
对于非缓存内容:
User -> CF -> Lambda -> User -> CF -> Lambda -> S3 -> Final response to the user
对于缓存的内容:
User -> CF(cf returns 301) -> User -> CF -> Final response to the user
因此,您在这种方法中获得了两个优势:
- 为您的用户减少延迟。
- 更少的 lambda 调用,这意味着你的账单更少。
对于您的第二个问题,我认为目前没有任何方法可以仅为 404 调用 Lambda@Edge。
希望这可以帮助!
推荐阅读
- swift - PDFView 中的透明背景颜色不再适用于 Mac Catalyst 13.0+
- python - 如何使用 regex 和 defaultdict 创建带有列表的字典
- java - 在 Ubuntu 中使用 javac 编译时出错
- postgresql - 我可以将 postgresql 配置为自动截断长字符串吗
- c - 调整 .bmp 文件的大小和结果文件的大小是错误的
- python - 运行此循环时出现错误
- node.js - javascript node.js 读取命令行流
- python - 如何使用在 WSL(Windows Ubuntu 16)中下载的 Anaconda 分发 Python 路径作为 VSCODE 中的主要 python
- google-cloud-platform - 如何在 Google Cloud Platform 的 Compute Engine 上安装 Jenkins?
- postgresql - 多个 UPDATE ... FROM 同一行不起作用