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 相关文章推荐
html下载本地
Jun 19 Javascript
用JS操作FRAME中的IFRAME及其内容的实现代码
Jul 26 Javascript
js类的静态属性和实例属性的理解
Oct 01 Javascript
火狐textarea输入法的bug的触发及解决
Jul 24 Javascript
javascript向后台传送相同属性的参数即数组参数
Feb 17 Javascript
jQuery使用removeClass方法删除元素指定Class的方法
Mar 26 Javascript
标准的js无缝滚动效果
Aug 30 Javascript
Scala解析Json字符串的实例详解
Oct 11 Javascript
angularjs实现天气预报功能
Jun 16 Javascript
Vue+Express实现登录注销功能的实例代码
May 05 Javascript
基于layui的下拉列表的数据回显方法
Sep 24 Javascript
使用vue编写h5公众号跳转小程序的实现代码
Nov 27 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支付宝手机网页支付类实例
2015/03/04 PHP
PHP判断文件是否被引入的方法get_included_files用法示例
2016/11/29 PHP
PHP实现十进制、二进制、八进制和十六进制转换相关函数用法分析
2017/04/25 PHP
php操作redis数据库常见方法实例总结
2020/02/20 PHP
jQuery使用手册之三 CSS操作
2007/03/24 Javascript
js实现运行代码需要刷新的解决方法
2007/08/18 Javascript
js列举css中所有图标的实现代码
2011/07/04 Javascript
Node.js生成HttpStatusCode辅助类发布到npm
2013/04/09 Javascript
js实现点击获取验证码倒计时效果
2021/01/28 Javascript
Node.js开发者必须了解的4个JS要点
2016/02/21 Javascript
快速移动鼠标触发问题及解决方法(ECharts外部调用保存为图片操作及工作流接线mouseenter和mouseleave)
2016/08/29 Javascript
简单的jQuery拖拽排序效果的实现(增强动态)
2017/02/09 Javascript
微信小程序 扎金花简单实例
2017/02/21 Javascript
详解在vue-cli3.0中自定css、js和图片的打包路径
2019/08/26 Javascript
Webpack设置环境变量的一些误区详解
2019/12/19 Javascript
[02:43]DOTA2英雄基础教程 德鲁伊
2014/01/13 DOTA
python 七种邮件内容发送方法实例
2014/04/22 Python
Python2与python3中 for 循环语句基础与实例分析
2017/11/20 Python
python将.ppm格式图片转换成.jpg格式文件的方法
2018/10/27 Python
Python实现计算文件MD5和SHA1的方法示例
2019/06/11 Python
python 解决pycharm运行py文件只有unittest选项的问题
2020/09/01 Python
Numpy中np.random.rand()和np.random.randn() 用法和区别详解
2020/10/23 Python
python基于pexpect库自动获取日志信息
2021/02/01 Python
python元组拆包实现方法
2021/02/28 Python
纯CSS3大转盘抽奖示例代码(响应式、可配置)
2017/01/13 HTML / CSS
Hotter Shoes英国官网:英伦风格,舒适的鞋子
2017/12/28 全球购物
加拿大时尚潮流大码女装购物网站:Addition Elle
2018/04/02 全球购物
乌克兰电子和家用电器商店:Foxtrot
2019/07/23 全球购物
自荐信格式技巧有哪些呢
2013/11/19 职场文书
大学生在校学习的自我评价
2014/02/18 职场文书
2014年五四青年节活动策划书
2014/04/22 职场文书
结婚保证书范文
2014/04/29 职场文书
2014年文秘工作总结
2014/11/25 职场文书
公司介绍信范文
2015/01/31 职场文书
七年级上册生物的课件
2019/08/07 职场文书
PHP基本语法
2021/03/31 PHP