如何用nodejs的http模块创建一个简单的静态资源服务器

发布时间:2021-07-16 17:43:11 作者:chen
来源:亿速云 阅读:808
# 如何用Node.js的http模块创建一个简单的静态资源服务器

## 前言

在现代Web开发中,静态资源服务器是基础但至关重要的组件。虽然Express等框架能快速搭建服务,但理解底层原理同样重要。本文将手把手教你用Node.js原生`http`模块构建一个静态资源服务器,涵盖核心实现、性能优化和错误处理。

---

## 一、项目初始化

首先创建项目目录并初始化:

```bash
mkdir static-server && cd static-server
npm init -y

安装必要依赖(非必须,但方便开发):

npm install mime-types --save

二、基础服务器搭建

创建server.js文件,编写最简HTTP服务器:

const http = require('http');
const fs = require('fs');
const path = require('path');

const PORT = 3000;

const server = http.createServer((req, res) => {
  // 请求处理逻辑将在这里实现
  res.end('Hello from static server!');
});

server.listen(PORT, () => {
  console.log(`Server running at http://localhost:${PORT}`);
});

此时运行node server.js访问localhost:3000会看到欢迎消息。


三、处理静态文件请求

1. 解析请求路径

const server = http.createServer((req, res) => {
  // 获取请求路径并规范化
  let filePath = path.join(
    __dirname,
    'public',
    req.url === '/' ? 'index.html' : req.url
  );
  
  // 处理路径遍历攻击
  filePath = path.normalize(filePath);
  if (!filePath.startsWith(path.join(__dirname, 'public'))) {
    res.statusCode = 403;
    return res.end('Forbidden');
  }
});

2. 读取文件内容

fs.readFile(filePath, (err, content) => {
  if (err) {
    if (err.code === 'ENOENT') {
      // 文件不存在
      res.statusCode = 404;
      res.end('File not found');
    } else {
      // 其他服务器错误
      res.statusCode = 500;
      res.end('Server error');
    }
  } else {
    // 成功读取文件
    res.end(content);
  }
});

四、完善响应头

1. 设置Content-Type

使用mime-types库自动识别MIME类型:

const mime = require('mime-types');

// 在成功读取文件后添加:
const contentType = mime.lookup(filePath) || 'application/octet-stream';
res.setHeader('Content-Type', contentType);

2. 缓存控制

添加浏览器缓存支持:

res.setHeader('Cache-Control', 'public, max-age=3600'); // 缓存1小时

五、性能优化

1. 使用文件流

避免内存溢出,改用流式传输:

const stream = fs.createReadStream(filePath);
stream.on('error', (err) => {
  // 错误处理
});
stream.pipe(res);

2. 压缩支持

添加gzip压缩(需zlib模块):

const zlib = require('zlib');

// 检查客户端是否支持gzip
const acceptEncoding = req.headers['accept-encoding'] || '';
if (acceptEncoding.includes('gzip')) {
  res.setHeader('Content-Encoding', 'gzip');
  stream.pipe(zlib.createGzip()).pipe(res);
} else {
  stream.pipe(res);
}

六、完整代码示例

const http = require('http');
const fs = require('fs');
const path = require('path');
const mime = require('mime-types');
const zlib = require('zlib');

const PORT = 3000;
const PUBLIC_DIR = path.join(__dirname, 'public');

const server = http.createServer((req, res) => {
  let filePath = path.join(
    PUBLIC_DIR,
    req.url === '/' ? 'index.html' : req.url
  );
  
  // 安全校验
  filePath = path.normalize(filePath);
  if (!filePath.startsWith(PUBLIC_DIR)) {
    res.statusCode = 403;
    return res.end('Forbidden');
  }

  // 设置Content-Type
  const contentType = mime.lookup(filePath) || 'application/octet-stream';
  res.setHeader('Content-Type', contentType);

  // 缓存控制
  res.setHeader('Cache-Control', 'public, max-age=3600');

  const stream = fs.createReadStream(filePath);
  
  stream.on('error', (err) => {
    if (err.code === 'ENOENT') {
      res.statusCode = 404;
      res.end('Not Found');
    } else {
      res.statusCode = 500;
      res.end('Server Error');
    }
  });

  // 压缩支持
  const acceptEncoding = req.headers['accept-encoding'] || '';
  if (acceptEncoding.includes('gzip')) {
    res.setHeader('Content-Encoding', 'gzip');
    stream.pipe(zlib.createGzip()).pipe(res);
  } else {
    stream.pipe(res);
  }
});

server.listen(PORT, () => {
  console.log(`Static server running at http://localhost:${PORT}`);
});

七、测试与使用

  1. 创建public目录和测试文件:

    mkdir public
    echo '<h1>Welcome</h1>' > public/index.html
    
  2. 启动服务器:

    node server.js
    
  3. 访问测试:

    • http://localhost:3000 显示index.html
    • http://localhost:3000/不存在的文件 返回404

八、扩展建议

  1. 目录列表:实现类似Apache的目录浏览功能
  2. HTTPS支持:添加https模块支持
  3. 环境变量:通过dotenv管理配置
  4. 日志系统:记录访问日志

结语

通过这个约100行的实现,我们完成了支持缓存、压缩、安全校验的静态服务器。虽然不如专业框架强大,但理解了核心原理后,你能更好地驾驭上层框架。建议尝试继续扩展功能,比如添加Range请求支持或ETag验证。

完整项目代码可参考:GitHub示例仓库 “`

(注:实际字符数约1500字,可根据需要调整内容细节)

推荐阅读:
  1. 简单理解nodejs模块的使用
  2. http模块怎么在NodeJS中使用

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

node.js

上一篇:RedHat中怎么移除MongoDB

下一篇:Web开发中客户端跳转与服务器端跳转有什么区别

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》