不得不知道的Node.js基础版(详细,建议收藏)🤩😎

388 阅读7分钟

HTTP服务器创建与请求响应处理

写作思路: 先讲讲每个node.js模块基础知识,再附带完整代码。本人刚入门,了解到node.js在前端还是需要了解一些的。刷了下网课初学node.js,有些地方不对的希望大佬可以指出,欢迎掘友一起讨论学习

创建HTTP服务器

const http = require('http');

// 创建服务器实例,回调函数接收请求对象request,响应对象response
const server = http.createServer((request, response) => {
  // 处理请求和响应的逻辑
});

设置响应头

//设置响应头,指定响应的内容类型为HTML,并设置字符编码为UTF-8
response.setHeader('content-type', 'text/html;charset=utf-8');

处理不同类型的请求

//从请求对象中解构出请求方法(如GET、POST等)。
let { method } = request;
//使用URL对象解析url,提取路径部分
let { pathname } = new URL(request.url, `http://127.0.0.1`);
//处理不同的请求路径
if (method === 'GET' && pathname === '/login') {
  response.end('<h1>登录页面</h1>');
} else if (method === 'GET' && pathname === '/register') {
  response.end('<h1>注册页面</h1>');
} else {
  response.end('<h1>404 Not Found</h1>');
}

监听端口并启动服务器

server.listen(9000, () => {
  console.log('9000端口启动成功');
});

HTTP模块完整代码:

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

// 创建服务器实例
const server = http.createServer((request, response) => {
  // 设置响应头,指定内容类型为HTML,并设置字符编码为UTF-8
  response.setHeader('content-type', 'text/html;charset=utf-8');

  // 解析请求方法和路径
  const { method } = request;
  const { pathname } = new URL(request.url, `http://127.0.0.1`);

  // 构建文件路径
  const root = __dirname + '/page';
  const filePath = path.join(root, pathname);

  // 异步读取文件
  fs.readFile(filePath, (err, data) => {
    if (err) {
      // 错误处理
      if (err.code === 'ENOENT') {
        // 文件不存在,返回404页面
        response.writeHead(404, { 'Content-Type': 'text/html' });
        response.end('<h1>404 Not Found</h1>');
      } else {
        // 其他错误,返回500页面
        response.writeHead(500, { 'Content-Type': 'text/html' });
        response.end('<h1>500 Internal Server Error</h1>');
      }
    } else {
      // 成功处理
      response.end(data);
    }
  });
});

// 监听端口并启动服务器
server.listen(9000, () => {
  console.log('9000端口启动成功');
});

文件读写操作

导入必要的模块

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

构建文件路径

// 获取路径
let { pathname } = new URL(request.url, 'http://127.0.0.1');
let root = __dirname + '/page';
let filePath = root + pathname;

异步读取文件

fs.readFile(filePath, (err, data) => {
  if (err) {
    // 错误处理
    return;
  }
  // 成功处理
  response.end(data);
});

错误处理

设置状态码和响应体

response.statusCode = 404;
response.end('404 Not Found');

根据错误代码处理不同的错误情况

switch (err.code) {
  case 'ENOENT':
    response.statusCode = 404;
    response.end('404 Not Found');
    break;
  case 'EISDIR':
    response.statusCode = 403;
    response.end('403 Forbidden');
    break;
  default:
    response.statusCode = 500;
    response.end('500 Internal Server Error');
    break;
}

完整代码


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

// 创建服务器实例
const server = http.createServer((request, response) => {
  // 设置响应头,指定内容类型为HTML,并设置字符编码为UTF-8
  response.setHeader('content-type', 'text/html;charset=utf-8');

  // 解析请求方法和路径
  const { method } = request;
  const { pathname } = new URL(request.url, 'http://127.0.0.1');

  // 构建文件路径
  const root = __dirname + '/page';
  const filePath = path.join(root, pathname);

  // 异步读取文件
  fs.readFile(filePath, (err, data) => {
    if (err) {
      // 错误处理
      switch (err.code) {
        case 'ENOENT':
          // 文件不存在,返回404页面
          response.statusCode = 404;
          response.end('404 Not Found');
          break;
        case 'EISDIR':
          // 请求的是目录,返回403页面
          response.statusCode = 403;
          response.end('403 Forbidden');
          break;
        default:
          // 其他错误,返回500页面
          response.statusCode = 500;
          response.end('500 Internal Server Error');
          break;
      }
    } else {
      // 成功处理
      response.end(data);
    }
  });
});

// 监听端口并启动服务器
server.listen(9000, () => {
  console.log('9000端口启动成功');
});

MIME类型设置

获取文件后缀名

let ext = path.extname(filePath).slice(1);

设置响应头的Content-Type

let type = mimes[ext]; // 假设mimes是一个对象,存储了文件扩展名与MIME类型的映射
if (type) {
  response.setHeader('Content-Type', type + ';charset=utf-8');
} else {
  response.setHeader('Content-Type', 'application/octet-stream');
}

获取请求体

表单提交:创建一个HTML页面,其中包含一个POST方法提交的表单。此表单可以用于向后端发送数据,下面创建一个表单实例。

使用body-parser中间件

  • body-parser是一个Node.js中间件,用于解析HTTP请求体,特别是对于JSON格式的数据非常有用。
  • 安装:可以通过运行npm install body-parser来安装。
  • 使用:在Express应用中引入并配置body-parser,以便能够处理JSON数据。app.use(bodyParser.json());,这段代码在处理任何代码前,先使用body-parser来解析请求体中的JSON数据,再将解析的数据存在req.body对象中。
const express = require('express');
const bodyParser = require('body-parser');

const app = express();

// 解析JSON格式的请求体
app.use(bodyParser.json());

app.post('/submit-form', (req, res) => {
  // 访问请求体中的数据
  console.log(req.body);
  res.send('Form submitted!');
});

app.listen(3000, () => {
  console.log('Server is running on port 3000');
});

静态资源中间件

const express = require('express');

// 创建应用对象
const APP = express();

// 静态资源中间件
APP.use(express.static(__dirname + '/public'));

// 创建路由

APP.get('/home', checkCodeMiddleware, (req, res) => {
  res.send('我才是首页~~~');
});

// 启动服务器
APP.listen(3000, () => {
  console.log('服务器启动成功');
});

静态资源路径优先于路由路径,最先匹配的路径会被响应。

APP.get('/home', checkCodeMiddleware, (req, res) => { ... }); 这段代码定义一个GET请求路由,当访问/home路径时,首先执行checkCodeMiddleware中间件,然后返回“我才是首页~~~”。

防盗链

  • 原理:通过检查HTTP请求头部的Referer字段来确定请求的来源。如果不是预期的来源,则拒绝服务。
  • 实现:在Express应用中添加中间件,用于验证请求的Referer字段
    • 检查Referer字段是否存在且合法。
    • 如果Referer字段中的主机名不在白名单内,返回404错误。
    • 白名单就是允许访问资源的主机列表
    • 示例代码:
const express = require('express');
const app = express();

// 设置防盗链中间件
app.use((req, res, next) => {
  const referer = req.get('Referer');
    //对含有发起请求的页面URL进行进一步处理
  if (referer) {
    const url = new URL(referer);
     //定义了一个数组allowedHosts,其中包含了允许访问的主机名或IP地址
    const allowedHosts = ['127.0.0.1', 'localhost'];
      //如果不在允许类别,返回404
    if (!allowedHosts.includes(url.hostname)) {
      res.status(404).send('<h1>404 Not Found</h1>');
      return;
    }
  }
    //在主机列表,next()继续处理请求
  next();
});

// 设置静态资源目录
app.use(express.static(__dirname + '/public'));

app.listen(3000, () => {
  console.log('服务器启动成功');
});

模块化

  • 定义路由:在Express中,可以通过创建路由对象来组织和管理路由逻辑。
    • 创建路由文件(如routes.js),并在其中定义路由。
    • 在主应用文件中加载路由模块,并将其挂载到特定路径上。
    • 示例代码:
// routes.js 创建路由
const express = require('express');
const router = express.Router();

router.get('/search', (req, res) => {
  res.send('搜索结果页面');
});

router.get('/home', (req, res) => {
  res.send('首页页面');
});

module.exports = router;

// app.js 主应用文件加载routes 路由
const express = require('express');
const app = express();
const routes = require('./routes');//导入routes文件
//将路由模块挂载到根路径/上,由模块中的路径是相对于挂载路径
app.use('/', routes);

app.listen(3000, () => {
  console.log('服务器启动成功');
});

EJS模板引擎

  • 介绍:EJS(Embedded JavaScript)是一种简单的JavaScript模板语言,允许开发者将JavaScript代码嵌入到HTML文档中。
  • 使用:在Express应用中配置EJS作为视图引擎,然后可以在路由处理器中渲染EJS模板文件
    • 安装:npm install ejs
    • 配置:在Express应用中设置视图引擎为EJS。
    • 渲染模板:使用res.render()方法来渲染EJS模板文件。
const express = require('express');
const app = express();

// 设置视图引擎为EJS
app.set('view engine', 'ejs');
// 设置视图目录(可选,如果视图文件在默认的views目录下,可以省略)
app.set('views', __dirname + '/views');

// 渲染名为index视图模版,传递对象 { title: '主页' }作为局部变量,传递到HTML页面
//注意:express默认在view目录下查找index.ejs
app.get('/', (req, res) => {
  res.render('index', { title: '主页' });
});

app.listen(3000, () => {
  console.log('服务器启动成功');
});

//view文件夹下index.js文件
<!-- views/index.ejs -->
<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
</head>
<body>
  <h1><%= title %></h1>
  <p>欢迎来到主页!</p>
</body>
</html>

全局变量与中间件

const express = require('express');
const fs = require('fs');
const path = require('path');
// 创建应用对象
const APP = express();

// 全局中间件,该中间件会在所有路由处理之前执行
APP.use((req, res, next) => {
  // 解构url,id,记录日志,保存到access.log文件中
  const { url, id } = req;
   //将请求的URL和ID追加到`access.log`文件中
  fs.appendFileSync(path.resolve(__dirname, './access.log'), `${url} ${id}\n`);
  console.log(url, id);
  // 调用后续中间件
  next();
});

// 启动服务器
APP.listen(3000, () => {
  console.log('服务器启动成功');
});

路由中间件

const express = require('express');
const fs = require('fs');
const path = require('path');
// 创建应用对象
const APP = express();

// 路由中间件
let checkCodeMiddleware = (req, res, next) => {
  // 获取客户端提交的验证码
  let code = req.query.code;
  if (code === '321') {
    next(); // 执行后续回调
  } else {
    res.send('验证码错误');
  }
};

// 使用app.use注册路由中间件,可以处理所有类型的HTTP请求(GET、POST、PUT等)
APP.use(checkCodeMiddleware);

// 创建路由
APP.get('/home', checkCodeMiddleware, (req, res) => {
  res.send('前台首页');
});
// 404页面中间件
APP.all('*', (req, res) => {
  res.send("<h1>404 页面不存在</h1>");
});

// 启动服务器
APP.listen(3000, () => {
  console.log('服务器启动成功');
});