公司一个非常老的项目需要增加需求,使用的原生html、js、css,没有使用react、vue之类的框架的情况下使用http-proxy-middleware拦截请求进行代理
初始化package.json
首先你的电脑上要有node环境,控制台输出一下
输入npm init
根据提示输入项目信息(一路回车就好,也可以直接复制)
C:\Web\test>node -v
v18.16.1 //输出版本号就有node环境
C:\Web\test>npm init //初始化package.json
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.
See `npm help init` for definitive documentation on these fields
and exactly what they do.
Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.
Press ^C at any time to quit.
package name: (test) test
version: (1.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to C:\Web\test\package.json:
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC"
}
Is this OK? (yes) yes
C:\Web\test>
安装依赖
输入npm install nodemon http-proxy-middleware
nodemon
的作用是你本地代码发生变化时自动更新服务
http-proxy-middleware
是代理发送出去的请求
C:\Web\test>npm install nodemon http-proxy-middleware
added 39 packages in 8s
5 packages are looking for funding
run `npm fund` for details
添加启动命令
安装结束在package.json
scripts 处添加 "dev": "nodemon index.js"
(这样比较优雅)
{
"name": "test",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"dev": "nodemon index.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"http-proxy-middleware": "^3.0.2",
"nodemon": "^3.1.7"
}
}
编写入口文件
入口文件为index.js,在根目录创建index.js
使用node的path得到文件地址,fs模块读取文件,os模块获取当前局域网网关,http模块将读到的文件映射到局域网
需要代理的真实域名在注释处替换即可
const http = require('http');
const fs = require('fs');
const url = require('url');
const path = require('path');
const os = require('os');
const { createProxyMiddleware: proxyMiddleWare } = require('http-proxy-middleware');
// 监听所有网络接口
const hostname = getLocalIp();
const port = 3000;
const server = http.createServer((req, res) => {
res.statusCode = 200;
const parsedUrl = url.parse(req.url, true);
const filePath = path.join(__dirname, parsedUrl.pathname);
if (parsedUrl.pathname.startsWith('/api1')) {
//拦截'/api'开头的请求进行代理
console.log('代理api1');
const proxyMiddleware = proxyMiddleWare({
target: 'https://sues.cn/', //目标域名既你要代理的域名
changeOrigin: true,
secure: false,
pathRewrite: {
'^/api1': '',
},
onProxyReq: (proxyReq, req, res) => {
proxyReq.setHeader('Cookie', 'JSESSIONID=62E0AA24BE5B6196399E853530431277');
},
});
return proxyMiddleware(req, res, () => {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Proxy failed');
});
}
if (parsedUrl.pathname.startsWith('/api2')) {
//拦截'/api2'开头的请求进行代理
console.log('代理api2');
const proxyMiddleware = proxyMiddleWare({
target: 'https://workflow.cn/', //目标域名既你要代理的域名
changeOrigin: true,
secure: false,
pathRewrite: {
'^/api2': '',
},
onProxyReq: (proxyReq, req, res) => {
proxyReq.setHeader('Cookie', 'JSESSIONID=62E0AA24BE5B6196399E853530431277');
},
});
return proxyMiddleware(req, res, () => {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('Proxy failed');
});
}
fs.readFile(filePath, (err, data) => {
if (err) {
if (err.code === 'ENOENT') {
res.writeHead(404, { 'Content-Type': 'text/plain' });
res.end('404 Not Found');
} else {
res.writeHead(500, { 'Content-Type': 'text/plain' });
res.end('500 Internal Server Error');
}
return;
}
const contentType = getContentType(filePath);
res.setHeader('Content-Type', contentType);
res.end(data);
});
});
server.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
// 获取当前局域网 IP 地址
function getLocalIp() {
const interfaces = os.networkInterfaces();
for (const name of Object.keys(interfaces)) {
for (const interface of interfaces[name]) {
const { address, family, internal } = interface;
if (family === 'IPv4' && !internal && address.includes('192.168')) {
return address;
}
}
}
return 'http://localhost/';
}
//获取资源类型
function getContentType(filePath) {
const ext = path.extname(filePath).toLowerCase();
switch (ext) {
case '.html':
return 'text/html';
case '.css':
return 'text/css';
case '.js':
return 'application/javascript';
case '.json':
return 'application/json';
case '.png':
return 'image/png';
case '.jpg':
case '.jpeg':
return 'image/jpeg';
case '.gif':
return 'image/gif';
default:
return 'application/octet-stream';
}
}
启动
输入npm run dev
启动!
会打印出你当前网关的局域网,我这里是http://192.168.61.87:3000/
按照你当前项目目录访问
C:\Web\test>npm run dev
> test@1.0.0 dev
> nodemon index.js
[nodemon] 3.1.7
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,cjs,json
[nodemon] starting `node index.js`
Server running at http://192.168.61.87:3000/
需要代理的请求开头一定要和拦截的保持一致!
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>http-proxy-middleware</title>
</head>
<body>
<h1>原生html使用http-proxy-middleware代理,解决接口跨域</h1>
<button id="send">发送请求</button>
<button id="send2">发送请求</button>
</body>
<script>
const context = '/api1';
const context2 = '/api2';
const api = {
http1: context + '/getUserInfo',
http2: context2 + '/getUserInfo2',
};
document.querySelector('#send').addEventListener('click', async function () {
const res = await fetch(api.http1);
console.log(res);
});
document.querySelector('#send2').addEventListener('click', async function () {
const res = await fetch(api.http2);
console.log(res);
});
</script>
</html>
发送请求代理成功时可以看到终端打印
运行截图
仓库地址
稀土掘金搜索 ZHYCH 即可找到我学习更多前端小技巧,未经作者允许请勿转载