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 相关文章推荐
cnblogs中在闪存中屏蔽某人的实现代码
Nov 14 Javascript
jquery中获取元素的几种方式小结
Jul 05 Javascript
仿百度联盟对联广告实现代码
Aug 30 Javascript
JavaScript 封装一个tab效果源码分享
Sep 15 Javascript
多种JQuery循环滚动文字图片效果代码
Jun 23 Javascript
jquery取消事件冒泡的三种方法(推荐)
May 28 Javascript
基于AngularJS前端云组件最佳实践
Oct 20 Javascript
Node.js中process模块常用的属性和方法
Dec 13 Javascript
js实现淡入淡出轮播切换功能
Jan 13 Javascript
VUE-Table上绑定Input通过render实现双向绑定数据的示例
Aug 27 Javascript
Vue的编码技巧与规范使用详解
Aug 28 Javascript
优化Vue中date format的性能详解
Jan 13 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中curl使用指南
2015/02/05 PHP
php利用ffmpeg提取视频中音频与视频画面的方法详解
2017/06/07 PHP
PHP中的日期时间处理利器实例(Carbon)
2017/06/09 PHP
显示、隐藏密码
2006/07/01 Javascript
用showModalDialog弹出页面后,提交表单总是弹出一个新窗口
2009/07/18 Javascript
setTimeout内不支持jquery的选择器的解决方案
2015/04/28 Javascript
再谈JavaScript线程
2015/07/10 Javascript
jQuery实现大转盘抽奖活动仿QQ音乐代码分享
2015/08/21 Javascript
jQuery 实现评论等级好评差评特效
2016/05/06 Javascript
Webpack打包慢问题的完美解决方法
2017/03/16 Javascript
Angular.js中控制器之间的传值详解
2017/04/24 Javascript
JavaScript学习笔记之惰性函数示例详解
2017/08/27 Javascript
学习jQuery中的noConflict()用法
2018/09/28 jQuery
微信小程序实现拍照画布指定区域生成图片
2019/07/18 Javascript
浅谈小程序globalData的那些事儿
2019/11/01 Javascript
JS正则表达式验证密码强度
2020/03/18 Javascript
[01:33:30]DOTA2-DPC中国联赛 正赛 RNG vs Phoenix BO3 第二场 2月5日
2021/03/11 DOTA
python错误处理详解
2014/09/28 Python
python中numpy包使用教程之数组和相关操作详解
2017/07/30 Python
Python实现统计给定字符串中重复模式最高子串功能示例
2018/05/16 Python
python实现微信机器人: 登录微信、消息接收、自动回复功能
2019/04/29 Python
Python 中list ,set,dict的大规模查找效率对比详解
2019/10/11 Python
python Jupyter运行时间实例过程解析
2019/12/13 Python
Python有参函数使用代码实例
2020/01/06 Python
Pandas时间序列基础详解(转换,索引,切片)
2020/02/26 Python
matlab、python中矩阵的互相导入导出方式
2020/06/01 Python
python属于跨平台语言码
2020/06/09 Python
使用OpenCV对车道进行实时检测的实现示例代码
2020/06/19 Python
Python用access判断文件是否被占用的实例方法
2020/12/17 Python
HTML5实时语音通话聊天MP3压缩传输3KB每秒
2019/08/28 HTML / CSS
柯基袜:Corgi Socks
2017/01/26 全球购物
英文版餐饮运营管理求职信
2013/11/06 职场文书
写好自荐信需做到的5要点
2014/03/07 职场文书
法人授权委托书范本
2014/04/04 职场文书
个人德育工作总结
2015/03/05 职场文书
2016年优秀共产党员先进事迹材料
2016/02/29 职场文书