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 相关文章推荐
JavaScript异步调用定时方法并停止该方法实现代码
Mar 16 Javascript
document.createElement()用法
Mar 13 Javascript
JavaScript函数获取事件源的小例子
May 14 Javascript
jquery自定义插件开发之window的实现过程
May 06 Javascript
javascript时间戳和日期字符串相互转换代码(超简单)
Jun 22 Javascript
Html5 js实现手风琴效果
Apr 17 Javascript
微信小程序组件 contact-button(客服会话按钮)详解及实例代码
Jan 10 Javascript
微信小程序教程系列之设置标题栏和导航栏(7)
Jun 29 Javascript
JavaScript同源策略和跨域访问实例详解
Apr 03 Javascript
微信小程序开发之获取用户手机号码(php接口解密)
May 17 Javascript
使用vue3重构拼图游戏的实现示例
Jan 25 Vue.js
JavaScript分页组件使用方法详解
Jul 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
PHP简单数据库操作类实例【支持增删改查及链式操作】
2016/10/10 PHP
PHP设计模式之原型模式定义与用法详解
2018/04/03 PHP
js 多浏览器分别判断代码
2010/04/01 Javascript
JavaScript 一行代码,轻松搞定浮动快捷留言-V2升级版
2010/04/02 Javascript
js动画(animate)简单引擎代码示例
2012/12/04 Javascript
JavaScript实现QueryString获取GET参数的方法
2013/07/02 Javascript
Javascript高级技巧分享
2014/02/25 Javascript
从零学jquery之如何使用回调函数
2014/05/16 Javascript
14个有用的Jquery技巧分享
2015/01/08 Javascript
js实现可控制左右方向的无缝滚动效果
2016/05/29 Javascript
jQuery解析与处理服务器端返回xml格式数据的方法详解
2016/07/04 Javascript
jQuery设置Easyui校验规则(推荐)
2016/11/21 Javascript
JavaScript屏蔽Backspace键的实现代码
2017/11/02 Javascript
jQuery实现表单动态添加数据并提交的方法
2018/07/19 jQuery
前端js中的事件循环eventloop机制详解
2019/05/15 Javascript
vue路由守卫,限制前端页面访问权限的例子
2019/11/11 Javascript
ES2020 新特性(种草)
2020/01/12 Javascript
[03:26]回顾2015国际邀请赛中国区预选赛
2015/06/09 DOTA
好用的Python编辑器WingIDE的使用经验总结
2016/08/31 Python
利用Python命令行传递实例化对象的方法
2016/11/02 Python
Django自定义插件实现网站登录验证码功能
2017/04/19 Python
Pycharm学习教程(7)虚拟机VM的配置教程
2017/05/04 Python
利用python微信库itchat实现微信自动回复功能
2017/05/18 Python
python爬虫获取淘宝天猫商品详细参数
2020/06/23 Python
Python大数据之使用lxml库解析html网页文件示例
2019/11/16 Python
python中numpy.empty()函数实例讲解
2021/02/05 Python
社区工作感言
2014/02/21 职场文书
文秘大学生求职信
2014/02/25 职场文书
公司演讲稿开场白
2014/08/25 职场文书
2014年营销工作总结
2014/11/22 职场文书
庆元旦主持词
2015/07/06 职场文书
大学生志愿者心得体会
2016/01/15 职场文书
《跨越海峡的生命桥》教学反思
2016/02/18 职场文书
分享Python获取本机IP地址的几种方法
2022/03/17 Python
零基础学java之循环语句的使用
2022/04/10 Java/Android
CSS list-style-type属性使用方法
2023/05/21 HTML / CSS