我正在使用 Firebase 托管
cleanUrls
。
Firebase Hosting 还允许在所有 URL 中强制使用尾部斜杠:
"hosting": {
"trailingSlash": true
}
如果用户请求页面时不使用尾部斜杠,这将强制进行 301 重定向。但是,我只想对目录强制执行此重定向(即:用于提供
index.html
文件)。
根据文档,您可以将
trailingSlash
保留为未定义。这将:
/foo/bar/page
200 (/foo/bar/page.html
)/foo/bar/
200 (/foo/bar/index.html
)/foo/bar
200 (/foo/bar/index.html
)最后一部分是出乎意料的,因为我想对目录强制使用尾部斜杠。
如何对所有目录强制执行 301 重定向,以仅对它们强制执行尾部斜杠?例如:
/foo/bar/page
200 (/foo/bar/page.html
)/foo/bar/
200 (/foo/bar/index.html
)/foo/bar
重定向到 /foo/bar/
请注意,可能有很多目录,因此为了可维护性,最好采用避免为每个目录编写单独规则的解决方案。
让
/foo/bar
返回 404 也可以,但首选 301。
首先,确保您的
firebase.json
不会在全局强制执行尾部斜杠以允许单独处理:
{
"hosting": {
"cleanUrls": true,
"trailingSlash": false,
// Additional configurations like redirects and rewrites will go here
}
}
由于 Firebase Hosting 的配置 不会像传统服务器那样自动区分文件和目录,因此您可以尝试手动为已知目录路径指定重定向规则。虽然这需要对每个目录进行初始设置,但它是每个目录的一次性配置。
User Request Firebase Hosting Action Served Content
-----------------------------------------------------------------------------------------
/foo/bar/page ---> Serve Directly (cleanUrls) ---> /foo/bar/page.html
/foo/bar/ ---> Serve Directly ---> /foo/bar/index.html
/foo/bar ---> 301 Redirect (via redirects) ---> /foo/bar/
然后使用包罗万象的
rewrite
规则来处理所有其他路径,直接提供 .html
文件。
{
"hosting": {
"cleanUrls": true,
"redirects": [
{
"source": "/foo/bar",
"destination": "/foo/bar/",
"type": 301
}
// Add similar rules for other directories
],
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
// Other configurations
}
}
redirects
下的每个条目都指定一个目录,该目录应该有一个尾部斜杠。当用户尝试访问不带尾部斜杠的 /foo/bar
时,他们会被重定向到 /foo/bar/
,并带有 301 状态代码。但是:每个目录都需要一个重定向规则。对于具有许多目录的项目,这可能会变得很麻烦。
如果您的站点经常生成新目录,您需要相应地更新您的
firebase.json
或考虑可以动态完成目录检查的服务器端解决方案。
请注意,可能有很多目录,因此为了可维护性,最好采用避免为每个目录编写单独规则的解决方案。
然后,您需要使用 Cloud Functions for Firebase 或 Firebase Hosting 与 Cloud Run 的集成 以编程方式处理请求。这允许您实现逻辑来检查请求的路径是否对应于目录并通过重定向强制执行尾部斜杠。
使用云函数,该函数会拦截 HTTP 请求,检查请求 URL 是否对应于目录(通过检查它是否映射到公共目录中的
index.html
文件),并重定向到带有尾部斜杠的相同 URL(如果)所以。const functions = require('firebase-functions');
const path = require('path');
const os = require('os');
const fs = require('fs-extra');
exports.addTrailingSlash = functions.https.onRequest(async (req, res) => {
// Extract the path from the request URL
const urlPath = req.path;
// Construct the file system path to where the file would be located
const filePath = path.join(os.tmpdir(), 'public', urlPath);
// Check if an index.html exists for this path
if (await fs.pathExists(path.join(filePath, 'index.html'))) {
// Directory exists, redirect to path with trailing slash
res.redirect(301, `${urlPath}/`);
} else {
// Not a directory or no index.html, handle normally
// That might involve serving the file directly, showing a 404, etc.
}
});
通过此云功能路由请求将使用
rewrites
中的 firebase.json
功能,允许该功能相应地处理和重定向目录请求。firebase.json
需要重写规则来将流量引导至此函数进行处理:
{
"hosting": {
"rewrites": [
{
"source": "**",
"function": "addTrailingSlash"
}
],
// Other configurations
}
}
但是:通过云功能路由所有请求可能会引入延迟:请检查潜在的性能影响。
使用 Cloud Functions 或 Cloud Run 实现逻辑会增加项目的复杂性,并且可能会根据您的使用情况产生成本,因此您可能需要执行一些Cloud FinOps。