Node.js 表示静态资产的大小写敏感度
Case sensitivity of Node.js Express static assets
如何设置 express.static
的路由是否区分大小写?例如Express 是否应该通过提供名为 Image.jpeg
.
的本地文件来处理对 image.jpeg
的请求
调用 express.Router([options])
时有一个 caseSensitive 选项(如 http://expressjs.com/en/4x/api.html 中定义),但调用 express.static(root, [options])
时没有这个选项(文档相同 link ).
默认情况下,从不区分大小写的卷 (/Mac OS X) 到区分大小写的卷 (/Linux),我得到不同的服务静态文件的行为。这会导致我们的应用程序出现不一致的错误 - 其中大小写不匹配的内容在 Mac OS X 下本地工作,但在部署到 Linux 服务器时失败。
我也想要这个,所以我想出了一个快速处理大小写不匹配的 404 请求的方法。
它不是特别有效,所以我只运行它在开发中。它只检查文件名。它不检查文件上方文件夹的大小写。
使用方法:
var express = require('express');
var app = express();
// You can do this before or after the express() call
// But it must come before express.static() is called
var inDevelopment = (process.NODE_ENV || 'local') === 'local';
if (inDevelopment) {
require('./modules/makeExpressStaticCaseSensitive')(express);
}
app.use(express.static(path.join(__dirname, 'public_html')));
脚本module/makeExpressStaticCaseSensitive.js
module.exports = function (express) {
var fs = require('fs')
var pathlib = require('path');
var parseUrl = require('express/node_modules/parseurl')
var oldStatic = express.static;
var newStatic = function (root, options) {
var opts = Object.create(options || null);
var originalHandler = oldStatic(root, options);
var wrappedHandler = function (req, res, next) {
var filepath = pathlib.join(root, parseUrl(req).pathname);
var dirpath = pathlib.dirname(filepath);
var filename = pathlib.basename(filepath);
// @todo Reading the entire directory listing and then searching it is quite inefficient for large folders
// We should find a more efficient way to do this for one file at a time
fs.readdir(dirpath, function (err, files) {
if (err) return next(err);
var fileIsThere = files.indexOf(filename) >= 0;
if (fileIsThere) {
originalHandler(req, res, next);
} else {
res.status(404).end();
}
});
};
return wrappedHandler;
};
express.static = newStatic;
};
我写了一个更高效的版本,它缓存 readdir()
的输出几秒钟,并检查整个路径,但它有点长。
我还得到了一些关于简单替代解决方案的建议:
Set a policy that all your static files and paths should be in lowercase.
Enforce the policy on the files by adding a build step that checks them.
Enforce the policy on requests by adding some middleware that rejects requests to the static folder if any uppercase characters are found in the path.
我最近遇到了这个问题,并对 express.static 的底层代码进行了调试。除了使命名一致之外,我找不到该场景的解决方案。但我认为分享幕后发生的事情是个好主意。没有自定义行为的选项,区分大小写由主机文件系统决定(MacOS APFS 对我来说默认区分大小写)。
express.static
实际上是使用 npm 包 serve-static
而 serve-static
使用 npm 包 send
到 return 文件。
并且 send 实际上使用 Node.js 的 fs.stat
在 returning 文件之前检查文件是否存在。该调用是否区分大小写取决于 Express.js 的主机文件系统。对于区分大小写的主机文件系统,调用将 return 和找不到文件的错误。
这是导致问题的代码的摘录
fs.stat(path, function onstat (err, stat) {
if (err && err.code === 'ENOENT' && !extname(path) && path[path.length - 1] !== sep) {
// not found, check extensions
return next(err)
}
if (err) return self.onStatError(err)
if (stat.isDirectory()) return self.redirect(path)
self.emit('file', path, stat)
self.send(path, stat)
})
我没有找到任何可以从 Express 传递给它的允许自定义行为的选项。 express.static 还执行许多重要功能,例如为文件设置响应 headers(缓存等),因此在没有等效替代品的情况下删除它也不是一个好的解决方案。
如何设置 express.static
的路由是否区分大小写?例如Express 是否应该通过提供名为 Image.jpeg
.
image.jpeg
的请求
调用 express.Router([options])
时有一个 caseSensitive 选项(如 http://expressjs.com/en/4x/api.html 中定义),但调用 express.static(root, [options])
时没有这个选项(文档相同 link ).
默认情况下,从不区分大小写的卷 (/Mac OS X) 到区分大小写的卷 (/Linux),我得到不同的服务静态文件的行为。这会导致我们的应用程序出现不一致的错误 - 其中大小写不匹配的内容在 Mac OS X 下本地工作,但在部署到 Linux 服务器时失败。
我也想要这个,所以我想出了一个快速处理大小写不匹配的 404 请求的方法。
它不是特别有效,所以我只运行它在开发中。它只检查文件名。它不检查文件上方文件夹的大小写。
使用方法:
var express = require('express');
var app = express();
// You can do this before or after the express() call
// But it must come before express.static() is called
var inDevelopment = (process.NODE_ENV || 'local') === 'local';
if (inDevelopment) {
require('./modules/makeExpressStaticCaseSensitive')(express);
}
app.use(express.static(path.join(__dirname, 'public_html')));
脚本module/makeExpressStaticCaseSensitive.js
module.exports = function (express) {
var fs = require('fs')
var pathlib = require('path');
var parseUrl = require('express/node_modules/parseurl')
var oldStatic = express.static;
var newStatic = function (root, options) {
var opts = Object.create(options || null);
var originalHandler = oldStatic(root, options);
var wrappedHandler = function (req, res, next) {
var filepath = pathlib.join(root, parseUrl(req).pathname);
var dirpath = pathlib.dirname(filepath);
var filename = pathlib.basename(filepath);
// @todo Reading the entire directory listing and then searching it is quite inefficient for large folders
// We should find a more efficient way to do this for one file at a time
fs.readdir(dirpath, function (err, files) {
if (err) return next(err);
var fileIsThere = files.indexOf(filename) >= 0;
if (fileIsThere) {
originalHandler(req, res, next);
} else {
res.status(404).end();
}
});
};
return wrappedHandler;
};
express.static = newStatic;
};
我写了一个更高效的版本,它缓存 readdir()
的输出几秒钟,并检查整个路径,但它有点长。
我还得到了一些关于简单替代解决方案的建议:
Set a policy that all your static files and paths should be in lowercase.
Enforce the policy on the files by adding a build step that checks them.
Enforce the policy on requests by adding some middleware that rejects requests to the static folder if any uppercase characters are found in the path.
我最近遇到了这个问题,并对 express.static 的底层代码进行了调试。除了使命名一致之外,我找不到该场景的解决方案。但我认为分享幕后发生的事情是个好主意。没有自定义行为的选项,区分大小写由主机文件系统决定(MacOS APFS 对我来说默认区分大小写)。
express.static
实际上是使用 npm 包 serve-static
而 serve-static
使用 npm 包 send
到 return 文件。
并且 send 实际上使用 Node.js 的 fs.stat
在 returning 文件之前检查文件是否存在。该调用是否区分大小写取决于 Express.js 的主机文件系统。对于区分大小写的主机文件系统,调用将 return 和找不到文件的错误。
这是导致问题的代码的摘录
fs.stat(path, function onstat (err, stat) {
if (err && err.code === 'ENOENT' && !extname(path) && path[path.length - 1] !== sep) {
// not found, check extensions
return next(err)
}
if (err) return self.onStatError(err)
if (stat.isDirectory()) return self.redirect(path)
self.emit('file', path, stat)
self.send(path, stat)
})
我没有找到任何可以从 Express 传递给它的允许自定义行为的选项。 express.static 还执行许多重要功能,例如为文件设置响应 headers(缓存等),因此在没有等效替代品的情况下删除它也不是一个好的解决方案。