您好,登錄后才能下訂單哦!
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; } }
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持億速云。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。