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为iframe的body添加click事件的实现代码
Apr 07 Javascript
javascript 使td内容不换行不撑开
Nov 29 Javascript
jquery load事件(callback/data)使用方法及注意事项
Feb 06 Javascript
jquery动态改变form属性提交表单
Jun 03 Javascript
浅析vue数据绑定
Jan 17 Javascript
bootstrap table之通用方法( 时间控件,导出,动态下拉框, 表单验证 ,选中与获取信息)代码分享
Jan 24 Javascript
Vue.js实战之通过监听滚动事件实现动态锚点
Apr 04 Javascript
react高阶组件经典应用之权限控制详解
Sep 07 Javascript
浅谈Angular4中常用管道
Sep 27 Javascript
详解JavaScript对数组操作(添加/删除/截取/排序/倒序)
Apr 28 Javascript
vue实现菜单切换功能
May 08 Javascript
node.js文件的复制、创建文件夹等相关操作
Feb 05 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和js交互一例-PHP教程,PHP应用
2007/01/03 PHP
攻克CakePHP系列三 表单数据增删改
2008/10/22 PHP
smarty的保留变量问题
2008/10/23 PHP
PHP使用CURL获取302跳转后的地址实例
2014/05/04 PHP
解密ThinkPHP3.1.2版本之模块和操作映射
2014/06/19 PHP
详解PHP编码转换函数应用技巧
2016/10/22 PHP
PHP实现将多个文件中的内容合并为新文件的方法示例
2017/06/10 PHP
PHP-FPM和Nginx的通信机制详解
2019/02/01 PHP
jquery中:input和input的区别分析
2011/07/13 Javascript
javaScript 删除字符串空格多种方法小结
2012/10/24 Javascript
用js正确判断用户名cookie是否存在的方法
2014/01/28 Javascript
javascript每日必学之运算符
2016/02/16 Javascript
jQuery简单实现点击文本框复制内容到剪贴板上的方法
2016/08/01 Javascript
javascript验证手机号和实现星号(*)代替实例
2016/08/16 Javascript
微信小程序 for 循环详解
2016/10/09 Javascript
利用React-router+Webpack快速构建react程序
2016/10/27 Javascript
Vue.js实现无限加载与分页功能开发
2016/11/03 Javascript
javascript实现复选框全选或反选
2017/02/04 Javascript
JS自定义函数实现时间戳转换成date的方法示例
2017/08/27 Javascript
js实现扫雷小程序的示例代码
2017/09/27 Javascript
javascript自定义事件功能与用法实例分析
2017/11/08 Javascript
vue视图不更新情况详解
2019/05/16 Javascript
python基础教程之python消息摘要算法使用示例
2014/02/10 Python
使用python实现strcmp函数功能示例
2014/03/25 Python
编程语言Python的发展史
2014/09/26 Python
Python 实现Windows开机运行某软件的方法
2018/10/14 Python
python KNN算法实现鸢尾花数据集分类
2019/10/24 Python
Pytorch.nn.conv2d 过程验证方式(单,多通道卷积过程)
2020/01/03 Python
python logging.info在终端没输出的解决
2020/05/12 Python
Python使用Matlab命令过程解析
2020/06/04 Python
Python3基于plotly模块保存图片表格
2020/08/03 Python
python实现测试工具(一)——命令行发送get请求
2020/10/19 Python
详解python第三方库的安装、PyInstaller库、random库
2021/03/03 Python
介绍下Java的输入输出流
2014/01/22 面试题
优秀员工评优方案
2014/06/13 职场文书
2019入党申请书格式和范文
2019/06/25 职场文书