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 相关文章推荐
jQuery技巧总结
Jan 01 Javascript
js操作滚动条事件实例
Jan 29 Javascript
js实现同一页面多个不同运动效果的方法
Apr 10 Javascript
jquery实现的V字形显示效果代码
Oct 27 Javascript
jquery zTree异步加载、模糊搜索简单实例分享
Mar 24 Javascript
AngularJS入门教程中SQL实例详解
Jul 27 Javascript
详解Angular 中 ngOnInit 和 constructor 使用场景
Jun 22 Javascript
vue .js绑定checkbox并获取、改变选中状态的实例
Aug 24 Javascript
解决vue页面渲染但dom没渲染的操作
Jul 27 Javascript
解决vue中axios设置超时(超过5分钟)没反应的问题
Sep 04 Javascript
react 项目中引入图片的几种方式
Jun 02 Javascript
vue如何实现关闭对话框后刷新列表
Apr 08 Vue.js
浅谈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设计模式之命令模式的应用详解
2013/05/21 PHP
PHP递归遍历指定目录的文件并统计文件数量的方法
2015/03/24 PHP
PHP生成指定随机字符串的简单实现方法
2015/04/01 PHP
ECSHOP完美解决Deprecated: preg_replace()报错的问题
2016/05/17 PHP
PHP连接及操作PostgreSQL数据库的方法详解
2019/01/30 PHP
PHP实现会员账号单唯一登录的方法分析
2019/03/07 PHP
解决laravel资源加载路径设置的问题
2019/10/14 PHP
Laravel定时任务的每秒执行代码
2019/10/22 PHP
Javascript数组的排序 sort()方法和reverse()方法
2012/06/04 Javascript
javascript控制swfObject应用介绍
2012/11/29 Javascript
自己写的Javascript计算时间差函数
2013/10/28 Javascript
jQuery制作的别致导航有阴影背景高亮模式窗口
2014/04/15 Javascript
jquery中each遍历对象和数组示例
2014/08/05 Javascript
js兼容火狐显示上传图片预览效果的方法
2015/05/21 Javascript
js+css简单实现网页换肤效果
2015/12/29 Javascript
微信小程序 Image API实例详解
2016/09/30 Javascript
Jquery Easyui对话框组件Dialog使用详解(14)
2016/12/19 Javascript
js中删除数组中的某一元素实例(无下标时)
2017/02/28 Javascript
jquery select插件异步实时搜索实例代码
2017/10/20 jQuery
JSON是什么?有哪些优点?JSON和XML的区别?
2019/04/29 Javascript
JS使用setInterval计时器实现挑战10秒
2020/11/08 Javascript
Python实现的Kmeans++算法实例
2014/04/26 Python
在Lighttpd服务器中运行Django应用的方法
2015/07/22 Python
Python中列表和元组的使用方法和区别详解
2020/12/30 Python
Python基础知识_浅谈用户交互
2017/05/31 Python
python实现while循环打印星星的四种形状
2019/11/23 Python
如何查看浏览器对html5的支持情况
2020/12/15 HTML / CSS
什么是WEB控件?使用WEB控件有哪些优势?
2012/01/21 面试题
英语自荐信常用语句
2013/12/13 职场文书
大学运动会入场词
2014/02/22 职场文书
2014年银行柜员工作总结
2014/11/12 职场文书
2014年保卫部工作总结
2014/11/21 职场文书
小学运动会入场词
2015/07/18 职场文书
2016年党员承诺书范文
2016/03/24 职场文书
vue中 this.$set的使用详解
2021/11/17 Vue.js
MySQL之MyISAM存储引擎的非聚簇索引详解
2022/03/03 MySQL