当前位置:Gxlcms > JavaScript > Koa代理Http请求的示例代码

Koa代理Http请求的示例代码

时间:2021-07-01 10:21:17 帮助过:14人阅读

Koa 代理http请求,解决跨域问题

1、为什么用Koa做跨域代理?

"最初为了解决跨域问题,我把站点部署到了nginx上就解决了问题。一次偶然的面试机会,面试官提出了一个假设我需要对提交api和api返回的数据进行适配,那么nginx是不是就无法满足了。当然这个问题的提出,让我考虑到其实如果自己搭一个站点,通过这个站点进行转发,适配第三方api的请求和应答不就好了。那么要搭一个站点的语言其实有很多,例如.net,java,nodejs,php...,那为什么最后选择nodejs呢?对于我来说最重要的原因,应该就是nodejs的轻量级和javascript语言亲和性。

2、搭建nodejs应用

由于Koa2刚出,毕竟学技术,那么就学最新的。

既然搭建程序那么就从程序的入口开始做,首先写程序的路由

  1. const fs = require('fs')
  2. const Router = require('koa-router');
  3. const {httpHandle} = require('../Infrastructure/httpHandle');
  4. const koaBody = require('koa-body')({
  5. multipart :true
  6. });
  7. const render = (page) => {
  8. return new Promise((resolve, reject) => {
  9. let viewUrl = `./view/${page}`
  10. fs.readFile(viewUrl, "binary", (err, data) => {
  11. if (err) {
  12. reject(err)
  13. } else {
  14. resolve(data)
  15. }
  16. })
  17. })
  18. }
  19. let api = new Router();
  20. api.get('*', httpHandle)
  21. .post('*', koaBody, httpHandle)
  22. .put('*', koaBody, httpHandle).del('*', koaBody, httpHandle);
  23. let common = new Router();
  24. common.get('*', async (ctx) => {
  25. ctx.body = await render('index.html');
  26. })
  27. let router = new Router();
  28. router.use('/api', api.routes(), api.allowedMethods());
  29. router.use('/', common.routes(), common.allowedMethods());
  30. module.exports = router;

其次就是处理代理的请求

  1. const httpRequest = (ctx) => {
  2. return new Promise((resolve) => {
  3. delete ctx.request.header.host;
  4. const options = {
  5. host,
  6. port,
  7. path: ctx.request.url.substr(4, ctx.request.url.length),
  8. method: ctx.request.method,
  9. headers: ctx.request.header
  10. }
  11. let requestBody='',
  12. body,
  13. head,
  14. chunks = [],
  15. fileFields,
  16. files,
  17. boundaryKey,
  18. boundary,
  19. endData,
  20. filesLength,
  21. totallength = 0;
  22. if (ctx.request.body) {
  23. console.log(ctx.request.header['content-type'])
  24. if (ctx.request.header['content-type'].indexOf('application/x-www-form-urlencoded') > -1) {
  25. requestBody = query.stringify(ctx.request.body);
  26. options.headers['Content-Length'] = Buffer.byteLength(requestBody)
  27. } else if (ctx.request.header['content-type'].indexOf('application/json') > -1) {
  28. requestBody = JSON.stringify(ctx.request.body);
  29. options.headers['Content-Length'] = Buffer.byteLength(requestBody)
  30. } else if (ctx.request.header['content-type'].indexOf('multipart/form-data') > -1) {
  31. fileFields = ctx.request.body.fields;
  32. files = ctx.request.body.files;
  33. boundaryKey = Math.random().toString(16);
  34. boundary = `\r\n----${boundaryKey}\r\n`;
  35. endData = `\r\n----${boundaryKey}--`;
  36. filesLength = 0;
  37. Object.keys(fileFields).forEach((key) => {
  38. requestBody += `${boundary}Content-Disposition:form-data;name="${key}"\r\n\r\n${fileFields[key]}`;
  39. })
  40. Object.keys(files).forEach((key) => {
  41. 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`;
  42. filesLength += Buffer.byteLength(requestBody,'utf-8') + files[key].size;
  43. })
  44. options.headers['Content-Type'] = `multipart/form-data; boundary=--${boundaryKey}`;
  45. options.headers[`Content-Length`] = filesLength + Buffer.byteLength(endData);
  46. } else {
  47. requestBody = JSON.stringify(ctx.request.body)
  48. options.headers['Content-Length'] = Buffer.byteLength(requestBody)
  49. }
  50. }
  51. const req = http.request(options, (res) => {
  52. res.on('data', (chunk) => {
  53. chunks.push(chunk);
  54. totallength += chunk.length;
  55. })
  56. res.on('end', () => {
  57. body = Buffer.concat(chunks, totallength);
  58. head = res.headers;
  59. resolve({head, body});
  60. })
  61. })
  62. ctx.request.body && req.write(requestBody);
  63. if (fileFields) {
  64. let filesArr = Object.keys(files);
  65. let uploadConnt = 0;
  66. filesArr.forEach((key) => {
  67. let fileStream = fs.createReadStream(files[key].path);
  68. fileStream.on('end', () => {
  69. fs.unlink(files[key].path);
  70. uploadConnt++;
  71. if (uploadConnt == filesArr.length) {
  72. req.end(endData)
  73. }
  74. })
  75. fileStream.pipe(req, {end: false})
  76. })
  77. } else {
  78. req.end();
  79. }
  80. })
  81. }

由此简单的几行代码就实现了通过nodejs实现跨域的请求代理。 github链接

nginx代理config配置 如下

  1. server {
  2. listen 1024;
  3. server_name tigrex:1024;
  4. root home/TuoTuo.v2.UI;
  5. index index.html;
  6. access_log logs/tigrex.access.log;
  7. error_log logs/tigrex.error.log;
  8. charset utf-8;
  9. location /api {
  10. proxy_pass http://127.0.0.1:1023/;
  11. proxy_set_header Host $host;
  12. proxy_redirect off;
  13. proxy_set_header X-Real-IP $remote_addr;
  14. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  15. }
  16. location / {
  17. try_files $uri $uri/ /index.html;
  18. }
  19. }

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

人气教程排行