Node 代理访问的实现


Posted in Javascript onSeptember 19, 2019

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的中间件原理 洋葱圈模型:

Node 代理访问的实现

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"
 }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
JavaScript 继承机制的实现(待续)
May 18 Javascript
jQuery让控件左右移动的三种实现方法
Sep 08 Javascript
jquery实现简单的遮罩层
Jan 08 Javascript
Javascript小技能总结(推荐)
Jun 02 Javascript
Vue.js每天必学之表单控件绑定
Sep 05 Javascript
JavaScript面向对象程序设计创建对象的方法分析
Aug 13 Javascript
JavaScript中set与get方法用法示例
Aug 15 Javascript
vue遍历对象中的数组取值示例
Nov 07 Javascript
ElementUI多个子组件表单的校验管理实现
Nov 07 Javascript
vue中根据时间戳判断对应的时间(今天 昨天 前天)
Dec 20 Javascript
解决Vue 给mapState中定义的属性赋值报错的问题
Jun 22 Javascript
原生js实现购物车
Sep 23 Javascript
浅谈laytpl 模板空值显示null的解决方法及简单的js表达式
Sep 19 #Javascript
微信小程序进入广告实现代码实例
Sep 19 #Javascript
解决layui数据表格Date日期格式的回显Object的问题
Sep 19 #Javascript
转换layUI的数据表格中的日期格式方法
Sep 19 #Javascript
js 判断当前时间是否处于某个一个时间段内
Sep 19 #Javascript
vue-froala-wysiwyg 富文本编辑器功能
Sep 19 #Javascript
关于layui toolbar和template的结合使用方法
Sep 19 #Javascript
You might like
如何在WIN2K下安装PHP4.04
2006/10/09 PHP
PHP面向对象程序设计之接口用法
2014/08/20 PHP
100行PHP代码实现socks5代理服务器
2016/04/28 PHP
laravel 5.4中实现无限级分类的方法示例
2017/07/27 PHP
laravel ORM关联关系中的 with和whereHas用法
2019/10/16 PHP
Js 订制自己的AlertBox(信息提示框)
2009/01/09 Javascript
javascript Onunload与Onbeforeunload使用小结
2009/12/31 Javascript
获取3个数组不重复的值的具体实现
2013/12/30 Javascript
点击显示指定元素隐藏其他同辈元素的方法
2014/02/19 Javascript
Javascript动画的实现原理浅析
2015/03/02 Javascript
javascript html5移动端轻松实现文件上传
2020/03/27 Javascript
深入理解ES6的迭代器与生成器
2017/08/19 Javascript
Nodejs 和Session 原理及实战技巧小结
2017/08/25 NodeJs
HTML5+JS+JQuery+ECharts实现异步加载问题
2017/12/16 jQuery
javascript中this的用法实践分析
2019/07/29 Javascript
vue-calendar-component 封装多日期选择组件的实例代码
2020/12/04 Vue.js
[50:22]完美盛典-2018年度红毯走秀
2018/12/16 DOTA
python使用datetime模块计算各种时间间隔的方法
2015/03/24 Python
Python导出数据到Excel可读取的CSV文件的方法
2015/05/12 Python
python 实现在txt指定行追加文本的方法
2018/04/29 Python
TensorFlow打印tensor值的实现方法
2018/07/27 Python
关于Numpy数据类型对象(dtype)使用详解
2019/11/27 Python
pycharm不能运行.py文件的解决方法
2020/02/12 Python
Django Path转换器自定义及正则代码实例
2020/05/29 Python
Python+pyftpdlib实现局域网文件互传
2020/08/24 Python
python BeautifulSoup库的安装与使用
2020/12/17 Python
python实现定时发送邮件
2020/12/23 Python
实用求职信范文分享
2013/12/25 职场文书
高中学生评语大全
2014/04/25 职场文书
学期评语大全
2014/04/30 职场文书
财务部副经理岗位职责范本
2014/06/17 职场文书
含预算的公司户外活动方案
2014/08/16 职场文书
党员教师自我剖析材料
2014/09/29 职场文书
实习单位推荐信
2015/03/27 职场文书
导游经典开场白——导游词
2019/04/17 职场文书
windows11选中自动复制怎么开启? Win11自动复制所选内容的方法
2022/07/23 数码科技