使用Node.js搭建静态资源服务详细教程

2020-06-17 06:48:12易采站长站整理

读取文件目录

现阶段,用

url: localhost:9527/testfolder
去访问一个指定root文件夹下真实存在的testfolder的文件夹,服务端会报错:

Error: EISDIR: illegal operation on a directory, read

要增添对目录访问的支持,我们重新整理下响应的步骤:

1.请求抵达时,首先判断url是否有尾部斜杠

2.如果有尾部斜杠,认为用户请求的是目录

如果目录存在
如果目录下存在默认页(如index.html),发送默认页
如果不存在默认页,发送目录下内容列表
如果目录不存在,返回404

3.如果没有尾部斜杠,认为用户请求的是文件

如果文件存在,发送文件
如果文件不存在,判断同名的目录是否存在
如果存在该目录,返回301,并在原url上添加上/作为要转到的location
如果不存在该目录,返回404

我们需要重写一下routeHandler内的逻辑:


routeHandler(pathName, req, res) {
fs.stat(pathName, (err, stat) => {
if (!err) {
const requestedPath = url.parse(req.url).pathname;
if (hasTrailingSlash(requestedPath) && stat.isDirectory()) {
this.respondDirectory(pathName, req, res);
} else if (stat.isDirectory()) {
this.respondRedirect(req, res);
} else {
this.respondFile(pathName, req, res);
}
} else {
this.respondNotFound(req, res);
}
});
}

继续补充respondRedirect方法:


respondRedirect(req, res) {
const location = req.url + '/';
res.writeHead(301, {
'Location': location,
'Content-Type': 'text/html'
});
res.end(`Redirecting to <a href='${location}'>${location}</a>`);
}

浏览器收到301响应时,会根据头部指定的location字段值,向服务器发出一个新的请求。

继续补充respondDirectory方法:


respondDirectory(pathName, req, res) {
const indexPagePath = path.join(pathName, this.indexPage);
if (fs.existsSync(indexPagePath)) {
this.respondFile(indexPagePath, req, res);
} else {
fs.readdir(pathName, (err, files) => {
if (err) {
res.writeHead(500);
return res.end(err);
}
const requestPath = url.parse(req.url).pathname;
let content = `<h1>Index of ${requestPath}</h1>`;
files.forEach(file => {
let itemLink = path.join(requestPath,file);
const stat = fs.statSync(path.join(pathName, file));
if (stat && stat.isDirectory()) {
itemLink = path.join(itemLink, '/');
}
content += `<p><a href='${itemLink}'>${file}</a></p>`;