在Web开发中,反向代理(Reverse Proxy)是一种常用的网络通信模式,尤其在构建高可用、高性能和安全的Web应用中扮演了重要角色。Node.js,通过其丰富的模块和库支持,可以轻松实现反向代理功能。
什么是反向代理?
反向代理是一种位于客户端和服务器之间的中介服务器,它接收来自客户端的请求,并将这些请求转发给后端服务器,然后将服务器的响应返回给客户端。这种机制不仅简化了客户端与服务器的直接交互,还提供了负载均衡、缓存、安全保护等多种功能。
主要功能
- 负载均衡:将请求分发到多个服务器上,平衡负载,避免单点故障。
- 安全性:隐藏后端服务器的真实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端口服务端的响应结果
输出结果:也是3000端口返回给客户端的结果,这样就实现了从80端口代理到3000端口,并且无跨域