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;
}
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。