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 相关文章推荐
有关DOM元素与事件的3个谜题
Nov 11 Javascript
基于Jquery 解决Ajax请求的页面 浏览器后退前进功能,页面刷新功能实效问题
Dec 11 Javascript
jquery通过ajax加载一段文本内容的方法
Jan 15 Javascript
再JavaScript的jQuery库中编写动画效果的指南
Aug 13 Javascript
jQuery实现TAB选项卡切换特效简单演示
Mar 04 Javascript
深入理解Angular2 模板语法
Aug 07 Javascript
bootstrap table分页模板和获取表中的ID方法
Jan 10 Javascript
JS对象是否拥有某属性如何判断
Feb 03 Javascript
深入学习 JavaScript中的函数调用
Mar 23 Javascript
微信小程序动态添加view组件的实例代码
May 23 Javascript
JS函数参数的传递与同名参数实例分析
Mar 16 Javascript
JavaScript快速调试的两个技巧
Nov 04 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/10/11 PHP
jQuery 判断元素上是否绑定了事件
2009/10/28 Javascript
《JavaScript高级程序设计》阅读笔记(一) ECMAScript基础
2012/02/27 Javascript
js onkeypress与onkeydown 事件区别详细说明
2012/12/13 Javascript
javascript遍历控件实例详细解析
2014/01/10 Javascript
使用js显示当前时间示例
2014/03/02 Javascript
如何使用jQuery技术开发ios风格的页面导航菜单
2015/07/29 Javascript
Node.js+Express配置入门教程详解
2016/05/19 Javascript
Webpack 服务器端代码打包的示例代码
2017/09/19 Javascript
ES6解构赋值实例详解
2017/10/31 Javascript
Angularjs中date过滤器失效的问题及解决方法
2018/07/06 Javascript
JS调用安卓手机摄像头扫描二维码
2018/10/16 Javascript
微信小程序实现二维码签到考勤系统
2020/01/16 Javascript
深入了解JS之作用域和闭包
2020/06/16 Javascript
解决vue cli4升级sass-loader(v8)后报错问题
2020/07/30 Javascript
vue项目里面引用svg文件并给svg里面的元素赋值
2020/08/17 Javascript
layui使用及简单的三级联动实现教程
2020/12/01 Javascript
[04:09]2014DOTA2国际邀请赛Ti西雅图 历届冠军相继出局 BBC综述今日比赛
2014/07/20 DOTA
Python用户推荐系统曼哈顿算法实现完整代码
2017/12/01 Python
python递归函数绘制分形树的方法
2018/06/22 Python
在python中将字符串转为json对象并取值的方法
2018/12/31 Python
pycharm new project变成灰色的解决方法
2019/06/27 Python
python读取word 中指定位置的表格及表格数据
2019/10/23 Python
使用python动态生成波形曲线的实现
2019/12/04 Python
pytorch动态网络以及权重共享实例
2020/01/06 Python
使用Tensorboard工具查看Loss损失率
2020/02/15 Python
Python自动登录QQ的实现示例
2020/08/28 Python
css3实现3D文本悬停改变效果的示例代码
2019/01/16 HTML / CSS
送货司机岗位职责
2013/12/11 职场文书
和平主题的演讲稿
2014/01/12 职场文书
餐饮采购员岗位职责
2014/03/15 职场文书
暑期政治学习心得体会
2014/09/02 职场文书
考试作弊检讨书1000字(5篇)
2014/10/19 职场文书
杭州黄龙洞导游词
2015/02/10 职场文书
教师信息技术学习心得体会
2016/01/21 职场文书
javascript中Set、Map、WeakSet、WeakMap区别
2022/12/24 Javascript