视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
Koa代理Http请求的示例代码
2020-11-27 22:06:30 责编:小采
文档

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

下载本文
显示全文
专题