前端代理
代理工具:charles,fiddler,whistle...
1. 本地node服务作为系统代理
1.1、起一个node服务,并手动设置系统代理
代理设置:Mac系统设置 > 网络 > WiFi > 代理 > 网页代理(HTTP)
- 服务器:你的ip地址
- 端口号:8886(node服务端口)
所有http请求响应内容为request url:${req.url}
import http from 'http'
const server = http.createServer((req, res) => {
console.log(`request url:${req.url}`)
res.setHeader('Content-Type', 'text/html;charset=utf-8')
res.end(`request url:${req.url}`)
})
server.listen(8886)
1.2、使用http-node转发到目标服务器,你可以针对请求不同的页面路径代理不同的目标源,还可以添加自定义响应头...
import type { IncomingMessage } from 'http'
import http from 'http'
import HttpProxy from 'http-proxy'
import url from 'url'
type Protocol = 'http' | 'https'
const getProtocol = (req: IncomingMessage): Protocol => {
if ((req.socket as any).encrypted) {
return 'https'
}
const proto = req.headers['X-Forwarded-Proto'] as Protocol | undefined
return typeof proto !== 'undefined' ? proto!.split(/\s*,\s*/, 1)[0] as Protocol : 'http';
}
const server = http.createServer((req, res) => {
const origin = `${getProtocol(req)}://${req.headers['host']}`
const path = url.parse(req.url || '').path
if (path?.match(/^\/api1/)) {
// 代理其他源
}
if (path?.match(/^\/api2/)) {
// 代理其他源
}
const proxyServer = new HttpProxy()
proxyServer.on('proxyRes', (proxyRes) => {
if (req.headers['host'] === 'xxx.com') {
// 添加自定义响应头
proxyRes.headers['X-my-custom-field'] = '11111-------11111'
}
})
proxyServer.web(req, res, {
target: origin,
changeOrigin: true
})
})
server.listen(8886)
2. vite、webpack工具代理配置
早期项目都是用webpack-dev-server(依赖express中间件http-proxy-middleware),这里举例vite的使用
// vite.config.ts
import { defineConfig } from "vite";
export default defineConfig((_config) => {
return {
// ...
server: {
proxy: {
"/api": {
target: "https://api.xxx.com",
changeOrigin: true,
configure(proxy, options) {
// proxy就是基于http-proxy创建的代理对象,vite依赖http-proxy
proxy.on("proxyRes", (proxyRes) => {
proxyRes.headers["X-my-custom-field"] = "111----111";
});
},
},
},
hmr: {
overlay: false,
},
host: "0.0.0.0",
},
};
});
3. Whistle代理工具
Whistle类似charles等其他代理工具,其主要是作为一款跨平台web调试代理工具,非常强大好用,官方文档
Whistle原理类似node代理,它与charles类似,安装完证书,即可代理https,以下是Whistle客户端工具Rules的配置,常用的功能见官方文档Whistle常用功能
# 转发:本地ip:port可以通过域名进行访问
# 调试不同端的环境(浏览器,微信webview,微信公众号开发,原生app webview h5,...)
172.16.22.117:5173 taobao.com test.com xxx.com
# 重定向
chaoshi.jd.com/aaa redirect://https://chaoshi.jd.com/liangfan
# 模拟bad request
taobao.com replaceStatus://400
# 针对所有请求新增跨域请求头(xhr请求,未绑定域名的阿里oss地址)
*/ resHeaders://{cors}
# 百度站点自定义html内容
www.baidu.com htmlBody://{test.html}
4. 代理请求头设置
看 http-proxy怎么处理的
XHeaders: function XHeaders(req, res, options) {
if(!options.xfwd) return;
var encrypted = req.isSpdy || common.hasEncryptedConnection(req);
var values = {
for : req.connection.remoteAddress || req.socket.remoteAddress,
port : common.getPort(req),
proto: encrypted ? 'https' : 'http'
};
['for', 'port', 'proto'].forEach(function(header) {
req.headers['x-forwarded-' + header] =
(req.headers['x-forwarded-' + header] || '') +
(req.headers['x-forwarded-' + header] ? ',' : '') +
values[header];
});
req.headers['x-forwarded-host'] = req.headers['x-forwarded-host'] || req.headers['host'] || '';
},
nginx做转发也需要处理
http {
server {
location ~* ^/(api|gw) {
proxy_pass 代理源;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $proxy_add_x_forwarded_proto;
}
}
}