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 相关文章推荐
js null undefined 空区别说明
Jun 13 Javascript
jquery.validate.js插件使用经验记录
Jul 02 Javascript
jQuery经过一段时间自动隐藏指定元素的方法
Mar 17 Javascript
JavaScript中创建字典对象(dictionary)实例
Mar 31 Javascript
JavaScript中判断两个字符串是否相等的方法
Jul 07 Javascript
JS日程管理插件FullCalendar中文说明文档
Feb 06 Javascript
使用MUI框架模拟手机端的下拉刷新和上拉加载功能
Sep 04 Javascript
vue.js实现点击后动态添加class及删除同级class的实现代码
Apr 04 Javascript
详解webpack4.x之搭建前端开发环境
Mar 28 Javascript
微信小程序实现获取用户信息并存入数据库操作示例
May 07 Javascript
用VsCode编辑TypeScript的实现方法
May 07 Javascript
在vue中对数组值变化的监听与重新响应渲染操作
Jul 17 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极大的增强功能和性能
2006/10/09 PHP
PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明
2011/12/05 PHP
PHP文件缓存类示例分享
2015/01/30 PHP
javascript 传统事件模型构造的事件监听器实现代码
2010/05/31 Javascript
利用js(jquery)操作Cookie的方法说明
2013/12/19 Javascript
javascript怎么禁用浏览器后退按钮
2014/03/27 Javascript
JS获得浏览器版本和操作系统版本的例子
2014/05/13 Javascript
jQuery提示效果代码分享
2014/11/20 Javascript
jquery+javascript编写国籍控件
2015/02/12 Javascript
jQuery使用hide方法隐藏页面上指定元素的方法
2015/03/30 Javascript
jQuery结合AJAX之在页面滚动时从服务器加载数据
2015/06/30 Javascript
用director.js实现前端路由使用实例
2017/01/27 Javascript
jQuery插件FusionCharts绘制2D双折线图效果示例【附demo源码】
2017/04/14 jQuery
three.js中文文档学习之通过模块导入
2017/11/20 Javascript
浅谈vue项目重构技术要点和总结
2018/01/23 Javascript
详解Webpack多环境代码打包的方法
2018/08/03 Javascript
vue项目首屏打开速度慢的解决方法
2019/03/31 Javascript
vue简单封装axios插件和接口的统一管理操作示例
2020/02/02 Javascript
js实现踩五彩块游戏
2020/02/08 Javascript
Vue组件通信$attrs、$listeners实现原理解析
2020/09/03 Javascript
[02:28]DOTA2英雄基础教程 狼人
2013/12/23 DOTA
python使用rsa加密算法模块模拟新浪微博登录
2014/01/22 Python
跟老齐学Python之开始真正编程
2014/09/12 Python
python unittest实现api自动化测试
2018/04/04 Python
python format 格式化输出方法
2018/07/16 Python
对Python subprocess.Popen子进程管道阻塞详解
2018/10/29 Python
Python中的上下文管理器相关知识详解
2019/09/19 Python
解决Numpy中sum函数求和结果维度的问题
2019/12/06 Python
日本索尼音乐商店:Sony Music Shop
2018/07/17 全球购物
什么是类的返射机制
2016/02/06 面试题
实习自我评价怎么写
2013/12/02 职场文书
室内拓展活动方案
2014/02/13 职场文书
高三学习决心书
2014/03/11 职场文书
原料仓管员岗位职责
2015/04/01 职场文书
预备党员入党感想
2015/08/10 职场文书
涨工资申请书应该怎么写?
2019/07/08 职场文书