Koa代理Http请求的示例代码


Posted in Javascript onOctober 10, 2018

Koa 代理http请求,解决跨域问题

1、为什么用Koa做跨域代理?

"最初为了解决跨域问题,我把站点部署到了nginx上就解决了问题。一次偶然的面试机会,面试官提出了一个假设我需要对提交api和api返回的数据进行适配,那么nginx是不是就无法满足了。当然这个问题的提出,让我考虑到其实如果自己搭一个站点,通过这个站点进行转发,适配第三方api的请求和应答不就好了。那么要搭一个站点的语言其实有很多,例如.net,java,nodejs,php...,那为什么最后选择nodejs呢?对于我来说最重要的原因,应该就是nodejs的轻量级和javascript语言亲和性。

2、搭建nodejs应用

由于Koa2刚出,毕竟学技术,那么就学最新的。

既然搭建程序那么就从程序的入口开始做,首先写程序的路由

const fs = require('fs')
const Router = require('koa-router');
const {httpHandle} = require('../Infrastructure/httpHandle');
const koaBody = require('koa-body')({
  multipart :true
});

const render = (page) => {
  return new Promise((resolve, reject) => {
    let viewUrl = `./view/${page}`
    fs.readFile(viewUrl, "binary", (err, data) => {
      if (err) {
        reject(err)
      } else {
        resolve(data)
      }
    })
  })
}

let api = new Router();

api.get('*', httpHandle)
  .post('*', koaBody, httpHandle)
  .put('*', koaBody, httpHandle).del('*', koaBody, httpHandle);

let common = new Router();
common.get('*', async (ctx) => {
  ctx.body = await render('index.html');
})

let router = new Router();
router.use('/api', api.routes(), api.allowedMethods());
router.use('/', common.routes(), common.allowedMethods());
module.exports = router;

其次就是处理代理的请求

const httpRequest = (ctx) => {
  return new Promise((resolve) => {
    delete ctx.request.header.host;
    const options = {
      host,
      port,
      path: ctx.request.url.substr(4, ctx.request.url.length),
      method: ctx.request.method,
      headers: ctx.request.header
    }
    let requestBody='',
      body,
      head,
      chunks = [],
      fileFields,
      files,
      boundaryKey,
      boundary,
      endData,
      filesLength,
      totallength = 0;

    if (ctx.request.body) {
      console.log(ctx.request.header['content-type'])
      if (ctx.request.header['content-type'].indexOf('application/x-www-form-urlencoded') > -1) {
        requestBody = query.stringify(ctx.request.body);
        options.headers['Content-Length'] = Buffer.byteLength(requestBody)
      } else if (ctx.request.header['content-type'].indexOf('application/json') > -1) {
        requestBody = JSON.stringify(ctx.request.body);
        options.headers['Content-Length'] = Buffer.byteLength(requestBody)
      } else if (ctx.request.header['content-type'].indexOf('multipart/form-data') > -1) {
        fileFields = ctx.request.body.fields;
        files = ctx.request.body.files;
        boundaryKey = Math.random().toString(16);
        boundary = `\r\n----${boundaryKey}\r\n`;
        endData = `\r\n----${boundaryKey}--`;
        filesLength = 0;

        Object.keys(fileFields).forEach((key) => {
          requestBody += `${boundary}Content-Disposition:form-data;name="${key}"\r\n\r\n${fileFields[key]}`;
        })

        Object.keys(files).forEach((key) => {
          requestBody += `${boundary}Content-Type: application/octet-stream\r\nContent-Disposition: form-data; name="${key}";filename="${files[key].name}"\r\nContent-Transfer-Encoding: binary\r\n\r\n`;
          filesLength += Buffer.byteLength(requestBody,'utf-8') + files[key].size;
        })

        options.headers['Content-Type'] = `multipart/form-data; boundary=--${boundaryKey}`;
        options.headers[`Content-Length`] = filesLength + Buffer.byteLength(endData);
      } else {
        requestBody = JSON.stringify(ctx.request.body)
        options.headers['Content-Length'] = Buffer.byteLength(requestBody)
      }
    }

    const req = http.request(options, (res) => {
      res.on('data', (chunk) => {
        chunks.push(chunk);
        totallength += chunk.length;
      })

      res.on('end', () => {
        body = Buffer.concat(chunks, totallength);
        head = res.headers;
        resolve({head, body});
      })
    })

    ctx.request.body && req.write(requestBody);

    if (fileFields) {
      let filesArr = Object.keys(files);
      let uploadConnt = 0;
      filesArr.forEach((key) => {
        let fileStream = fs.createReadStream(files[key].path);
        fileStream.on('end', () => {
          fs.unlink(files[key].path);
          uploadConnt++;
          if (uploadConnt == filesArr.length) {
            req.end(endData)
          }
        })
        fileStream.pipe(req, {end: false})
      })
    } else {
      req.end();
    }

  })
}

由此简单的几行代码就实现了通过nodejs实现跨域的请求代理。 github链接

nginx代理config配置 如下

server {
   listen     1024; 
   server_name   tigrex:1024;
   root      home/TuoTuo.v2.UI;
   index      index.html;
   access_log   logs/tigrex.access.log;
   error_log    logs/tigrex.error.log;

   charset     utf-8;
   
   location /api {
     proxy_pass  http://127.0.0.1:1023/;
     proxy_set_header Host $host;
     proxy_redirect off;
     proxy_set_header X-Real-IP $remote_addr;
     proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
   }  
   
   location / {
     try_files $uri $uri/ /index.html;     
    }
  }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
通过JAVAScript实现页面自适应
Jan 19 Javascript
小型js框架veryide.librar源代码
Mar 05 Javascript
一个用javascript写的select支持上下键、首字母筛选以及回车取值的功能
Sep 09 Javascript
javascript 实现简单的table排序及table操作练习
Dec 28 Javascript
js判断运行jsp页面的浏览器类型以及版本示例
Oct 30 Javascript
AngularJS自动表单验证
Feb 01 Javascript
js HTML5上传示例代码完整版
Oct 10 Javascript
浅述节点的创建及常见功能的实现
Dec 15 Javascript
JS实现京东首页之页面顶部、Logo和搜索框功能
Jan 12 Javascript
js 原型对象和原型链理解
Feb 09 Javascript
JS禁止浏览器右键查看元素或按F12审查元素自动关闭页面示例代码
Sep 07 Javascript
AjaxUpLoad.js实现文件上传
Mar 05 Javascript
解决js相同的正则多次调用test()返回的值却不同的问题
Oct 10 #Javascript
jQuery 获取除某指定对象外的其他对象 ( :not() 与.not())
Oct 10 #jQuery
微信小程序自定义组件的实现方法及自定义组件与页面间的数据传递问题
Oct 09 #Javascript
从零开始封装自己的自定义Vue组件
Oct 09 #Javascript
vue axios 简单封装以及思考
Oct 09 #Javascript
angularJS实现不同视图同步刷新详解
Oct 09 #Javascript
对angular 实时更新模板视图的方法$apply详解
Oct 09 #Javascript
You might like
php过滤html标记属性类用法实例
2014/09/23 PHP
详解Yii实现分页的两种方法
2017/01/14 PHP
PHP的mysqli_rollback()函数讲解
2019/01/23 PHP
关于javascript document.createDocumentFragment()
2009/04/04 Javascript
JavaScript Cookie 直接浏览网站分网址
2009/12/08 Javascript
jquery利用ajax调用后台方法实例
2013/08/23 Javascript
Javascript表单验证要注意的事项
2014/09/29 Javascript
jQuery实现折叠、展开的菜单组效果代码
2015/09/16 Javascript
简单介绍jsonp 使用小结
2016/01/27 Javascript
详解JavaScript设计模式开发中的桥接模式使用
2016/05/18 Javascript
JavaScript数据结构之二叉树的计数算法示例
2017/04/13 Javascript
详解Vue 普通对象数据更新与 file 对象数据更新
2017/04/26 Javascript
JS继承与闭包及JS实现继承的三种方式
2017/10/15 Javascript
vue axios 二次封装的示例代码
2017/12/08 Javascript
Angular2开发环境搭建教程之VS Code
2017/12/15 Javascript
浅谈React中的元素、组件、实例和节点
2018/02/27 Javascript
elementui更改el-dialog关闭按钮的图标d的示例代码
2020/08/04 Javascript
Python 40行代码实现人脸识别功能
2017/04/02 Python
python九九乘法表的实例
2017/09/26 Python
python爬虫headers设置后无效的解决方法
2017/10/21 Python
Python决策树和随机森林算法实例详解
2018/01/30 Python
PyQt5每天必学之滑块控件QSlider
2018/04/20 Python
python网络编程之多线程同时接受和发送
2019/09/03 Python
python3 实现调用串口功能
2019/12/26 Python
python中四舍五入的正确打开方式
2021/01/18 Python
CSS3中的元素过渡属性transition示例详解
2016/11/30 HTML / CSS
Luxplus丹麦:香水和个人护理折扣
2018/04/23 全球购物
类、抽象类、接口的差异
2016/06/13 面试题
Can a struct inherit from another struct? (结构体能继承结构体吗)
2016/09/25 面试题
个人承诺书
2014/03/26 职场文书
2014年语文教研组工作总结
2014/12/06 职场文书
律师函格式范本
2015/05/27 职场文书
分享一些Java的常用工具
2021/06/11 Java/Android
Go语言实现Base64、Base58编码与解码
2021/07/26 Golang
Javascript之datagrid查询详解
2021/09/15 Javascript
Python自动操作神器PyAutoGUI的使用教程
2022/06/16 Python