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 相关文章推荐
JqGrid web打印实现代码
May 31 Javascript
jQuery中on()方法用法实例详解
Feb 06 Javascript
jquery模拟进度条实现方法
Aug 03 Javascript
jquery中validate与form插件提交的方式小结
Mar 26 Javascript
jquery解析XML及获取XML节点名称的实现代码
May 18 Javascript
JavaScript实现自动切换图片代码
Oct 11 Javascript
jQuery.Validate表单验证插件的使用示例详解
Jan 04 Javascript
JS点击图片弹出文件选择框并覆盖原图功能的实现代码
Aug 25 Javascript
详解angular笔记路由之angular-router
Sep 12 Javascript
Vue2.0+ElementUI实现表格翻页的实例
Oct 23 Javascript
JavaScript常见鼠标事件与用法分析
Jan 03 Javascript
elementUI Tree 树形控件的官方使用文档
Apr 25 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
php共享内存段示例分享
2014/01/20 PHP
php实现三级级联下拉框
2016/04/17 PHP
Extjs Ajax 乱码问题解决方案
2009/04/15 Javascript
jQuery 常见开发使用技巧总结
2009/12/26 Javascript
基于Jquery的开发个代阴影的对话框效果代码
2011/07/28 Javascript
有关javascript的性能优化 (repaint和reflow)
2013/04/12 Javascript
easyui datagrid 键盘上下控制选中行示例
2014/03/31 Javascript
javascript中bind函数的作用实例介绍
2014/09/28 Javascript
javascript制作幻灯片(360度全景图片)
2015/07/28 Javascript
基于jQuery实现的仿百度首页滑动选项卡效果代码
2015/11/16 Javascript
javascript实现省市区三级联动下拉框菜单
2015/11/17 Javascript
javascript实现九宫格相加数值相等
2020/05/28 Javascript
Node.js编写组件的三种实现方式
2016/02/25 Javascript
js弹出窗口简单实现代码
2017/03/22 Javascript
限时抢购-倒计时的完整实例(分享)
2017/09/17 Javascript
Node.js学习教程之HTTP/2服务器推送【译】
2017/10/31 Javascript
浅谈使用React.setState需要注意的三点
2017/12/18 Javascript
three.js 入门案例详解
2018/01/23 Javascript
vue中引用阿里字体图标的方法
2018/02/10 Javascript
七行JSON代码把你的网站变成移动应用过程详解
2019/07/09 Javascript
微信小程序自定义菜单切换栏tabbar组件代码实例
2019/12/30 Javascript
js动态添加带圆圈序号列表的实例代码
2021/02/18 Javascript
[00:37]2016完美“圣”典风云人物:AMS宣传片
2016/12/06 DOTA
Python推导式简单示例【列表推导式、字典推导式与集合推导式】
2018/12/04 Python
漂亮的Django Markdown富文本app插件的实现
2019/01/02 Python
Python如何获得百度统计API的数据并发送邮件示例代码
2019/01/27 Python
Python Matplotlib简易教程(小白教程)
2020/07/28 Python
浅谈Selenium+Webdriver 常用的元素定位方式
2021/01/13 Python
Vans澳大利亚官网:购买鞋子、服装及配件
2019/09/05 全球购物
JSP和Servlet有哪些相同点和不同点,他们之间的联系是什么?
2015/10/22 面试题
税务专业毕业生自荐信
2013/11/10 职场文书
电脑教师的教学自我评价
2013/11/26 职场文书
小学英语教学反思
2014/01/30 职场文书
写自荐信的注意事项
2014/03/09 职场文书
大学三年计划书范文
2014/04/30 职场文书
高中政治教学反思
2016/02/23 职场文书