Node.js中的反向代理

375 阅读3分钟

在Web开发中,反向代理(Reverse Proxy)是一种常用的网络通信模式,尤其在构建高可用、高性能和安全的Web应用中扮演了重要角色。Node.js,通过其丰富的模块和库支持,可以轻松实现反向代理功能。

什么是反向代理?

反向代理是一种位于客户端和服务器之间的中介服务器,它接收来自客户端的请求,并将这些请求转发给后端服务器,然后将服务器的响应返回给客户端。这种机制不仅简化了客户端与服务器的直接交互,还提供了负载均衡、缓存、安全保护等多种功能。

image.png

主要功能

  • 负载均衡:将请求分发到多个服务器上,平衡负载,避免单点故障。
  • 安全性:隐藏后端服务器的真实IP,保护内部网络。
  • 缓存:缓存后端服务器的响应,减少服务器负担,加快响应速度。
  • SSL终止:在反向代理处处理SSL加密和解密,减轻后端服务器的压力。

Node.js中的反向代理实现

使用http-proxy-middleware

http-proxy-middleware是一个强大的HTTP请求代理中间件,适用于Express、Connect等Node.js的HTTP服务器框架。

安装模块

首先,你需要通过npm安装http-proxy-middleware模块:

npm install http-proxy-middleware

反向代理实现

实现从80端口代理到3000端口

1.新建配置文件test.config.js,进行代理的一些配置

const config = {
  server: {
    proxy: {
      '/api': {
        target: 'http://localhost:3000',
        changeOrigin: true,
      }
    }
  }
}

export default config;

2.新建index.js文件,实现80端口的服务端,并实现反向代理

import http from 'http';
import url from 'url';
import fs from 'fs';
import { createProxyMiddleware } from 'http-proxy-middleware'
// 引入配置文件,假设它包含了反向代理的配置信息
import config from './test.config.js';
// 读取当前目录下的index.html文件,并将其内容存储在html变量中
const html = fs.readFileSync('./index.html', 'utf-8')

const server = http.createServer((req, res) => {
  // 解析请求的URL,获取路径名(pathname)  
  const { pathname } = url.parse(req.url, true)
  // 从配置文件中获取所有反向代理的路径列表 
  const proxList = Object.keys(config.server.proxy)
  // 检查请求的pathname是否在反向代理的路径列表中  
  if (proxList.includes(pathname)) {
    // 如果是,则根据配置创建一个反向代理中间件  
    const proxy = createProxyMiddleware(config.server.proxy[pathname])
    // 使用该中间件处理请求和响应 
    proxy(req, res)
    return
  }
  res.writeHead(200, {
    'Content-Type': 'text/html;charset=utf-8'
  })
  res.end(html)
})

server.listen(80, () => {
  console.log('server is running at http://localhost:80')
})

3.新建test.js文件,实现3000端口的服务端

import http from 'http';
import url from 'url';

const server = http.createServer((req, res) => {
  const { pathname } = url.parse(req.url, true)
  if (pathname === '/api') {
    res.writeHead(200, {
      'Content-Type': 'text/json;charset=utf-8'
    })
    res.end('hello world')
  }
})

server.listen(3000, () => {
  console.log('server is running at http://localhost:3000')
})

4.新建index.html,输出响应结果

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8"
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    
</head>
<body>
  fetch('/api').then(res => res.text()).then(data => {
    console.log(data)
  })
</body>
</html>

运行结果:

访问80端口:http://localhost:80 ,可以看到api接口,3000端口服务端的响应结果

image.png

输出结果:也是3000端口返回给客户端的结果,这样就实现了从80端口代理到3000端口,并且无跨域

image.png