欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Koa代理Http请求的示例代码

程序员文章站 2023-11-03 15:47:58
koa 代理http请求,解决跨域问题 1、为什么用koa做跨域代理? "最初为了解决跨域问题,我把站点部署到了nginx上就解决了问题。一次偶然的面试机会,面...

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;     
    }
  }

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