likes
comments
collection
share

跟着小满zs学 nodejs —— 总结篇(三)

作者站长头像
站长
· 阅读数 6

http 模块

用于创建和处理 HTTP 服务器和客户端的核心模块。可创建 Web 服务器、代理服务器、文件服务器等

  • demo
const http = require('node:http'); // 引入 http 模块
const url = require('node:url'); // 引入 url 模块

// 创建 HTTP 服务器,并传入回调函数用于处理请求和生成响应
http.createServer((req, res) => {
  const { pathname, query } = url.parse(req.url, true); // 解析请求的 URL,获取路径和查询参数,传 true 是让 query 以对象格式输出

  if (req.method === 'POST') { // 检查请求方法是否为 POST
    if (pathname === '/post') { // 检查路径是否为 '/post'
      let data = '';
      req.on('data', (chunk) => {
        data += chunk; // 获取 POST 请求的数据
        console.log(data);
      });
      req.on('end', () => {
        res.setHeader('Content-Type', 'application/json'); // 设置响应头的 Content-Type 为 'application/json'
        res.statusCode = 200; // 设置响应状态码为 200
        res.end(data); // 将获取到的数据作为响应体返回
      });
    } else {
      res.setHeader('Content-Type', 'application/json'); // 设置响应头的 Content-Type 为 'application/json'
      res.statusCode = 404; // 设置响应状态码为 404
      res.end('Not Found'); // 返回 'Not Found' 作为响应体
    }
  } else if (req.method === 'GET') { // 检查请求方法是否为 GET
    if (pathname === '/get') { // 检查路径是否为 '/get'
      console.log(query.a); // 打印查询参数中的键名为 'a' 的值
      res.end('get success'); // 返回 'get success' 作为响应体
    }
  }
}).listen(98, () => {
  console.log('server is running on port 98'); // 打印服务器启动的信息
});

反向代理

充当服务器和客户端之间的中介,将客户端的请求转发到一个或多个后端服务器,并将后端服务器的响应返回给客户端

用于负载均衡、高可用性、缓存和性能优化、安全性、域名和路径重写

  • demo
const http = require('node:http');
const fs = require('node:fs')
const url = require('node:url')
const html = fs.readFileSync('./index.html') //给html文件起个服务
const {createProxyMiddleware} = require('http-proxy-middleware')
const config = require('./xm.config.js')
const server = http.createServer((req, res) => {
    const {pathname} = url.parse(req.url)
    const proxyList = Object.keys(config.server.proxy) //获取代理的路径
    if(proxyList.includes(pathname)){ //如果请求的路径在里面匹配到 就进行代理
        const proxy = createProxyMiddleware(config.server.proxy[pathname]) //代理
        proxy(req,res)
        return
    }
    console.log(proxyList)
    res.writeHead(200, {
        'Content-Type': 'text/html'
    })
    res.end(html) //返回html

})

server.listen(80) //监听端口
  • 反向代理服务器通过http-proxy-middleware与html文件做关联,接收html文件传来的请求,并反向代理到目标服务器
  • xm.config.js 配置文件
module.exports = {
    server:{
        proxy:{
        //代理的路径
            '/api': {
                target: 'http://localhost:3000', //转发的地址
                changeOrigin: true, //是否有跨域
            }
        }
    }
}

动静分离

将动态生成的内容(如动态网页、API请求)与静态资源(如HTML、CSS、JavaScript、图像文件)分开处理和分发,通过将动态内容和静态资源存储在不同的服务器或服务上,并使用不同的处理机制

实现动静分离的方法:

  • 使用反向代理服务器(如Nginx、Apache)将静态请求和动态请求转发到不同的后端服务器或服务
  • 将静态资源部署到CDN上,通过CDN分发静态资源,减轻源服务器的负载
  • 使用专门的静态文件服务器(如Amazon S3、Google Cloud Storage)存储和提供静态资源,而将动态请求交给应用服务器处理
import http from 'node:http' // 导入http模块

const server = http.createServer((req, res) => {
    const { url, method } = req

    // 处理静态资源
    if (method === 'GET' && url.startsWith('/static')) {
    }

    // 处理动态资源
    if ((method === 'GET' || method === 'POST') && url.startsWith('/api')) {
    }
})

server.listen(80) // 监听端口80

模拟:现有一页面上有静态资源和动态资源,用户请求该页面的域名的后续过程

  1. 用户首先发送请求到服务器,请求页面。

  2. 服务器接收到请求后,通过动静分离技术,将请求的处理分为请求静态资源和请求动态资源两部分。动态内容由应用服务器处理,而静态内容由专门的静态服务器处理。

  3. 对于用户请求的动态资源,如API请求,服务器直接处理并返回相应的数据。这些数据通常是根据用户的请求参数,或存储在数据库中的数据动态生成的。

  4. 对于用户请求的静态资源,如图片、CSS、JS文件等,服务器将请求转发到CDN(内容分发网络)。

  5. CDN查看是否有缓存的静态资源,如果有就直接返回给用户,如果没有则向源服务器请求该静态资源。

  6. 原服务器把静态资源提供给CDN,CDN将资源保存在缓存中,并同时将资源返回给用户。

  7. 用户的浏览器接收到返回的动态和静态资源,进行页面的渲染。

第一步中的服务器通常为应用服务器,用户请求首先会被发送到应用服务器,对于静态资源的请求,应用服务器通常会将请求重定向到CDN或静态资源服务器

应用程序框架 express

基于Node.js的HTTP模块而创建的,简化了处理HTTP请求、响应和中间件的过程

路由模块化、中间件生态系统、视图引擎支持

  • demo
import express from 'express';
import User from './src/user.js'  // 路由模块
import loggerMiddleware from './middleware/logger.js';  // 中间件

const app = express()  // express 是个函数

app.use(express.json())  //如果前端使用的是post并且传递json 需要注册此中间件 不然是undefined
app.use('/user', User)  // 注册路由模块,第一个参数自定义路由前缀
app.use(loggerMiddleware)  // 注册自定义的中间件

app.get('/', (req, res) => {
    console.log(req.query)  //get 用query 
    res.send('get')
})

app.post('/create', (req, res) => {
    console.log(req.body)  //post用body
    res.send('post')
})

app.get('/:id', (req, res) => {
    console.log(req.params)  //如果是动态参数用 params
    res.send('get id')
})

app.listen(3000, () => console.log('Listening on port 3000'))
  • src/user.js 路由模块
import express from 'express'

const router = express.Router() //路由模块

router.post('/login', (req, res) => {
    res.send('login')
})

router.post('/register', (req, res) => {
    res.send('register')
})

export default router

中间件 是处理HTTP请求和响应的函数,它位于请求和最终路由处理函数之间,可以对请求和响应进行修改、执行额外的逻辑或者执行其他任务,例如身份验证、日志记录和错误处理

中间件函数接收三个参数:req(请求对象)、res(响应对象)和next(下一个中间件函数)。通过调用next()方法,中间件可以将控制权传递给下一个中间件函数。如果中间件不调用next()方法,请求将被中止,不会继续传递给下一个中间件或路由处理函数

防盗链

指在网页或其他网络资源中,通过直接链接到其他网站上的图片、视频或其他媒体文件,从而显示在自己的网页上。这种行为通常会给被链接的网站带来额外的带宽消耗和资源浪费,而且可能侵犯了原始网站的版权

防止盗链方式:通过HTTP引用检查、使用Referrer检查、使用访问控制列表(ACL)、使用防盗链插件或脚本、使用水印技术

  • demo
import express from 'express';

const app = express();

const whitelist = ['localhost'];

// 防止热链中间件
const preventHotLinking = (req, res, next) => {
  const referer = req.get('referer'); // 获取请求头部中的 referer 字段
  if (referer) {
    const { hostname } = new URL(referer); // 从 referer 中解析主机名
    if (!whitelist.includes(hostname)) { // 检查主机名是否在白名单中
      res.status(403).send('Forbidden'); // 如果不在白名单中,返回 403 Forbidden
      return;
    }
  }
  next(); // 如果在白名单中,继续处理下一个中间件或路由
};

app.use(preventHotLinking); // 应用防止热链中间件
app.use('/assets', express.static('static')); // 处理静态资源请求 static 为文件目录,第一参数是资源链接前缀

app.listen(3000, () => {
  console.log('Listening on port 3000'); // 启动服务器,监听端口3000
});

关于响应头和请求头