Node 代理访问的实现
- 作者: Akric丶Jun
- 来源: 51数据库
- 2021-08-31
node代理访问
1. 场景
- 本地开发,代理访问,防止跨域(一般通过webpack配置代理即可),特殊情况如携带一些自定义的登录cookie则需要通过自己写node
- 作为一种server中间层,单线程异步可以缓解服务器压力。长链接websocket通常使用node搭建
2. 技术框架
- node - koa2 体量小,轻便易用。
- 路由koa-router koa配套路由,中间件支持async
- koa2-request 基于async对 request的封装,这里本人git上找的,可靠性带考量,若基于生产环境建议使用request自行封装
- koa-bodyparser 请求参数解析格式化-中间件
3. 上代码
3.1 创建应用 app.js
const koa = require('koa')
const bodyparser = require('koa-bodyparser')
// 路由
const router = require('./router')
const app = new koa()
app.use(
bodyparser({
// 返回的对象是一个键值对,当extended为false的时候,键值对中的值就为'string'或'array'形式,为true的时候,则可为任何数据类型。
extended: true
})
)
3.2 允许跨域 app.js
app.use(async (ctx, next) => {
ctx.set('access-control-allow-origin', '*')
ctx.set('access-control-allow-headers', 'content-type')
ctx.set(
'access-control-allow-methods',
'options,get,head,put,post,delete,patch'
)
await next()
})
3.2 使用路由
// app.js
app.use(router.routes())
// router.js
const router = require('koa-router')
let koarequest = require('./httprequest')
const router = new router()
router.get('/*', async (ctx, next) => {
const url = setquesturl(ctx.url)
try {
let res = await koarequest(url, 'get', ctx)
ctx.body = res
} catch (err) {
ctx.body = err
}
})
router.post('/*', async (ctx, next) => {
const url = setquesturl(ctx.url)
try {
let res = await koarequest(url, 'post', ctx)
ctx.body = res
} catch (err) {
ctx.body = err
}
})
function setquesturl(url) {
if (/^/t/.test(url)) {
return 'host1'+ url.replace(/^/t/, '')
}
if (/^/xt/.test(url)) {
return 'host2' + url.replace(/^/xt/, '')
}
}
module.exports = router
- router.get('/*', async (ctx, next) => {}) koa路由 ‘/*' 为通配符,匹配所有get请求;next方法调用表示进入下一个中间件;
- ctx请求上下文,ctx.request.body post请求参数
- koa的中间件原理 洋葱圈模型:

const koa = require('koa2');
const app = new koa();
// logger
app.use(async (ctx, next) => {
console.log('第一层洋葱 - 开始')
await next();
const rt = ctx.response.get('x-response-time');
console.log(`${ctx.method} ${ctx.url} - ${rt}`);
console.log('第一层洋葱 - 结束')
});
// x-response-time
app.use(async (ctx, next) => {
console.log('第二层洋葱 - 开始')
const start = date.now();
await next();
const ms = date.now() - start;
ctx.set('x-response-time', `${ms}ms`);
console.log('第二层洋葱 - 结束')
});
// response
app.use(async ctx => {
console.log('第三层洋葱 - 开始')
ctx.body = 'hello world';
console.log('第三层洋葱 - 结束')
});
app.listen(8000);
// 输出
第一层洋葱 - 开始
第二层洋葱 - 开始
第三层洋葱 - 开始
第三层洋葱 - 结束
第二层洋葱 - 结束
第一层洋葱 - 结束
setquesturl 此方法主要是将前端访问的路径,根据第一级转发到不同的host上
例如: /t -> host1
3.3 转发请求 httprequest.js
本例主要为了代理访问并携带cookie, const.js 为写死的要携带的cookie
let koa2req = require('koa2-request')
let constconfig = require('./const')
let itoken = constconfig.itoken
let koarequest = async function(url, method, ctx) {
let options = {
method: method,
uri: url,
timeout: 120000,
body: ctx
? {
...ctx.request.body
}
: null,
headers: {},
json: true // automatically stringifies the body to json
}
options.headers['cookie'] = `i-token=${itoken}` //设置cookie
let res = await koa2req(options)
return res.body
}
// node-mon
async function gettesttoken() {
if (!constconfig.itoken) {
let url = `http://xt.eqxiu.com/tui/app/radar/test/gettoken?companyid=${constconfig.companyid}&staffid=${constconfig.staffid}`
try {
let res = await koarequest(url, 'get')
itoken = res.obj
console.log('token已拿到:' + itoken)
} catch (e) {
console.log(e)
}
}
}
gettesttoken()
module.exports = koarequest
3.4 最后设置端口等
const app = require('./app')
//const createwebsocket = require('./websocket')
const server = require('http').createserver(app.callback())
server.settimeout(2 * 60 * 1000) //设置超时时间
const { port = 3000 } = process.env
server.listen(port, () => {
console.log(`listening on port ${port}`)
})
3.5 本地开发,热重启
安装 nodemon
yarn add nodemon
设置忽略监听
nodemon.josn node项目根目录下
{
"ignore": ["node_modules/*"] //忽略node_modules下文件修改的监听
}
package.josn
通过npm run server启动
{
"dependencies": {
"koa": "^2.8.1",
"koa-bodyparser": "^4.2.1",
"koa-router": "^7.4.0",
"koa2-request": "^1.0.4",
"nodemon": "^1.19.1"
},
"scripts": {
"server": "nodemon index.js"
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
推荐阅读
