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 相关文章推荐
网页自动跳转代码收集
Sep 27 Javascript
jquery DOM操作 基于命令改变页面
May 06 Javascript
javascript 使用 NodeList需要注意的问题
Mar 04 Javascript
jQuery实现文本框输入同步的方法
Jun 20 Javascript
JS控制按钮10秒钟后可用的方法
Dec 22 Javascript
jquery实现列表上下移动功能
Feb 25 Javascript
JS HTML5拖拽上传图片预览
Jul 18 Javascript
Javascript 判断两个IP是否在同一网段实例代码
Nov 28 Javascript
使用Bootrap和Vue实现仿百度搜索功能
Oct 26 Javascript
React如何避免重渲染
Apr 10 Javascript
Vue开发之封装上传文件组件与用法示例
Apr 25 Javascript
微信小程序 swiper 组件遇到的问题及解决方法
May 26 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
执行、获取远程代码返回:file_get_contents 超时处理的问题详解
2013/06/25 PHP
PHP数组排序函数合集 以及它们之间的联系分析
2013/06/27 PHP
解析:php调用MsSQL存储过程使用内置RETVAL获取过程中的return值
2013/07/03 PHP
php修改指定文件后缀的方法
2014/09/11 PHP
PHP生成网站桌面快捷方式代码分享
2014/10/11 PHP
基于swoole实现多人聊天室
2018/06/14 PHP
php实现数组重复数字统计实例
2018/09/30 PHP
用window.location.href实现刷新另个框架页面
2007/03/07 Javascript
js location.replace与location.reload的区别
2010/09/08 Javascript
在js文件中如何获取basePath处理js路径问题
2013/07/10 Javascript
JavaScript中SetInterval与setTimeout的用法详解
2015/11/10 Javascript
整理AngularJS框架使用过程当中的一些性能优化要点
2016/03/05 Javascript
javascript 实现动态侧边栏实例详解
2016/11/11 Javascript
JavaScript实现三级联动菜单实例代码
2017/06/26 Javascript
AngularJS实现表单元素值绑定操作示例
2017/10/11 Javascript
详解webpack4之splitchunksPlugin代码包分拆
2018/12/04 Javascript
在Vue中使用this.$store或者是$route一直报错的解决
2019/11/08 Javascript
使用python的chardet库获得文件编码并修改编码
2014/01/22 Python
在Python中使用mongoengine操作MongoDB教程
2015/04/24 Python
Python 正则表达式的高级用法
2016/12/04 Python
pandas多级分组实现排序的方法
2018/04/20 Python
numpy实现合并多维矩阵、list的扩展方法
2018/05/08 Python
Django使用redis缓存服务器的实现代码示例
2019/04/28 Python
Django框架模板语言实例小结【变量,标签,过滤器,继承,html转义】
2019/05/23 Python
Python使用MyQR制作专属动态彩色二维码功能
2019/06/04 Python
python basemap 画出经纬度并标定的实例
2019/07/09 Python
python接口调用已训练好的caffe模型测试分类方法
2019/08/26 Python
Python字符串大小写转换拼接删除空白
2019/09/19 Python
Python Tkinter Entry和Text的添加与使用详解
2020/03/04 Python
Python脚本导出为exe程序的方法
2020/03/25 Python
IDLE下Python文件编辑和运行操作
2020/04/25 Python
全面介绍python中很常用的单元测试框架unitest
2020/12/14 Python
教学评估实施方案
2014/03/16 职场文书
小学生五年级大队长竞选发言稿
2014/09/12 职场文书
2014年党员自我评价材料
2014/09/22 职场文书
win10重装系统后上不了网怎么办 win10重装系统网络故障的解决办法
2022/07/23 数码科技