为什么我的nodejs服务器崩溃,即使我正在处理正在发生的假定错误?



我正在处理我的第一个nodejs服务器示例,它大部分都在工作。然而,我注意到,如果我试图调用一个不存在的html文件,服务器将崩溃。我设法找到了一个变通方法(已经被注释掉了(,但我很好奇为什么原始代码没有像我预期的那样运行。在崩溃之前,我会看到所需的响应,然后服务器会崩溃,输出如下:

Server running at http://localhost:3000
Request for /aboutuss.html by method GET
ENOENT: no such file or directory, access '/Users/albertkhasky/NodeJS/node-http/public/aboutuss.html'
events.js:173
throw er; // Unhandled 'error' event
^
Error: ENOENT: no such file or directory, open '/Users/**********/NodeJS/node-http/public/aboutuss.html'
Emitted 'error' event at:
at fs.open (internal/fs/streams.js:117:12)
at FSReqCallback.args [as oncomplete] (fs.js:145:20)
npm ERR! code ELIFECYCLE
npm ERR! errno 1

这是代码:

const http = require('http');
const fs = require('fs');
const path = require('path');
const hostname = 'localhost'
const port = 3000;
const server = http.createServer((req, res) => {
console.log("Request for " + req.url + ' by method ' + req.method);

if(req.method == 'GET'){
var fileUrl;
if(req.url == '/'){
fileUrl = '/index.html';
}else{
fileUrl = req.url;
}
var filePath = path.resolve('./public' + fileUrl);
const fileExt = path.extname(filePath);
if(fileExt == '.html'){
// if (!fs.existsSync(path)) {
//     res.statusCode = 404;
//     res.setHeader('Content-Type', 'text/html');
//     res.end('<html><body><h1>Error: 404 ' + fileUrl +  ' HTML FILE NOT FOUND </h1></body></html>');
//     return;
// }
fs.access(filePath, fs.F_OK, (err) => {
if(err){
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html');
res.end('<html><body><h1>Error: 404 ' + fileUrl +  ' HTML FILE NOT FOUND </h1></body></html>');
console.log(err.message);
return;
}
})
}else{
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html');
res.end('<html><body><h1>Error: 404 ' + fileUrl +  ' none HTML file not found</h1></body></html>');
return;
}
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
fs.createReadStream(filePath).pipe(res);

}else{
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html');
res.end('<html><body><h1>Error: 404 ' + req.method +  ' not supported</h1></body></html>');
return;
}
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}`); //variables inside the string is the reason for backticks
});

注释掉的代码返回404的原因是您传递的是path,而不是filePath,所以每次都会失败。

fs.access()检查失败的原因是它是一个异步调用——回调检查err不会立即发生。当检查进行时,代码无条件地创建一个到不存在路径的读流。(这也是为什么不推荐使用的对fs.existsSync((的调用会在传递filePath时解决问题。(

如果您想等待fs.access调用发生,请在检查错误(如(后,将成功返回(创建readstream的位置(移到fs.access回调中

fs.access(filePath, fs.F_OK, (err) => {
if(err){
res.statusCode = 404;
res.setHeader('Content-Type', 'text/html');
res.end('<html><body><h1>Error: 404 ' + fileUrl +  ' HTML FILE NOT FOUND </h1></body></html>');
console.log(err.message);
return;
}
res.statusCode = 200;
res.setHeader('Content-Type', 'text/html');
fs.createReadStream(filePath).pipe(res);
})

执行操作的一种更有效的方法是对文件使用fs.open(),处理错误返回,然后使用fs.open()返回的fd使用fs.createReadStream()。这样一来,您就不会打开文件两次,也不会出现竞争条件。

最新更新