likes
comments
collection
share

搭建代理服务

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

在网络应用中,代理服务器起着非常重要的作用。代理服务器可以作为客户端和服务器之间的中间商,帮助它们之间进行通信。在本篇文章中,我们将从零开始搭建一个简单的代理服务器。

什么时候需要使用代理服务器

在开发过程中,可能会遇到 后端可能有多个服务器,不同的 ip 和端口号,而且还不支持跨域(不支持本地跨域),这时候就需要使用代理了

搭建代理的方式

  • 使用 nginx 搭建代理
  • 使用 webpack、vite 等工具
  • 使用后端语言搭建,例如 Node.js、Python 等

使用nginx搭建代理服务

配置一个简单的代理服务

修改 nginx 的配置文件

server {  
    listen 80;  
    server_name example.com;  
  
    location / {  
    }  
  
    location /api1 {  
        proxy_pass http://backend_server;  
        add_header 'Access-Control-Allow-Origin' '*';  
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';  
        add_header 'Access-Control-Allow-Headers' 'DNT,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Range';  
    }
}

在上面的配置中,我们将所有路径(/api)的请求代理到名为backend_server的后端服务器。proxy_pass指令定义了代理的目标地址,proxy_set_header指令用于设置请求头信息。

此外,我们使用add_header指令添加了跨域相关的响应头,允许来自所有来源(*)的跨域请求,并允许使用 GETPOSTOPTIONS 方法。我们还允许某些常见的请求头,这些请求头在跨域请求中通常会使用。

配置完成后, 检查NGINX配置文件的语法是否正确

nginx -t

重启 nginx 服务

nginx -s reload

配置多个端口号

http {  
    server {  
        listen 80;
        server_name example.com;
  
        location / {  
            proxy_pass http://backend_server_1;
        }
    }
    server {  
        listen 81;
        server_name example.com;
  
        location / {  
            proxy_pass http://backend_server_2;
        }
    }
}

使用 Koa 搭建代理服务

这里将完整代码放在了 github 上(点击这里查看),可以直接下载使用

安装下依赖

npm i koa、koa2-connect、http-proxy-middleware @koa/cors

首先导入了 koa、koa2-connect、http-proxy-middleware、cors(跨域资源共享),我们代理的服务是可配置的,这里我使用了 dotenv(管理环境变量)

我们要使用 typescript 来开发,下面安装 typescript 相关依赖

npm i typescript ts-node @types/koa -D

如果使用了 Bun ,可以不用安装 typescript 相关的依赖,因为 Bun 可以直接运行 ts 文件

设计

.env 文件中,用户可以

  • 方式1,指定要代理的域名(或ip)和端口号,即 HOST 和 PORT
    • 域名必须指定一个,且只能指定一个。
    • 端口号可以指定一个或多个,指定多个时要代理多个端口
  • 方式1,直接指定完整的域名+端口号。这里端口号不能相同
  • 指定 BASE,代理的基础路径,如 /api

注意: 因为相同端口号只能开启一个服务,多个域名必须使用不同端口才能使用代理服务。可以使用第二种方式

HOST=http://10.14.80.100
PORT=10027,10026

创建服务

在package.json 配置启动命令, 通过 npm start 来启动

{
  "scripts": {
    "start": "ts-node app"
  }
 }

{
  "scripts": {
    "start": "bun app.ts"
  }
 }

编写代理服务,每调用一次createApp 就代理一个新的服务

import Koa from 'koa'
import connect from 'koa2-connect'
import { createProxyMiddleware } from 'http-proxy-middleware'
import cors from '@koa/cors'

function createApp(app: Koa, target: string, port: string | number) {
  const proxy = createProxyMiddleware({
    target,
    changeOrigin: true
  })
  // 支持跨域
  app.use(cors())
  // 将 /api 的请求代理到 target 
  app.use(async (ctx, next) => {
    if (ctx.path.startsWith(BASE)) {
      await connect(proxy)(ctx, next)
    } else {
      await next()
    }
  })
  
  // 启动指定 port 服务
  app.listen(port, () => {
    console.log(`Proxy server is running on  \x1b[92mhttp://localhost:${port} \x1b[0m`)
  })
}

接下来编写接收 .env 文件的配置

import * as dotenv from 'dotenv'

dotenv.config()
const BASE = process.env['BASE'] || '/api'
const TARGETS = process.env['TARGET']?.trim()?.split(',')

if (TARGETS?.length) {
  TARGETS.forEach((target) => {
    const app = new Koa()
    target = target.trim()
    if(target){
      const port = target.split(':')[2]
      createApp(app, target, port)
    }
  })
} else {
  const hosts = process.env['PORT']?.split(',') || [8080]
  const host = process.env['HOST']
  if (!host) {
    throw new Error('请在 .env 文件中配置 HOST')
  }
  hosts.forEach((port) => {
    const app = new Koa()
    createApp(app, `${host.trim()}:${port.trim()}`, port.trim())
  })
}