Node做中转服务器转发接口


Posted in Javascript onOctober 18, 2017

由于项目在做前后端分离,牵扯跨域和夸协议问题,临时抱佛脚,选择用nodejs做中转,我想应该好多人都用它。但是做普通的表单转发没啥问题,当处理附件上传转发时,各种蛋疼,已解决!

1.项目比较特殊,后台拥有两个平台,一个java一个donet,比较鸡肋,具体什么原因就不解释了。

2.当做node转发时,刚开始没有转发文件的操作,就做的很简单,用户传过来啥就,拦截到,进行转发,一切都很ok!

3.文件转发,就很麻烦。我的思路,将用户上传的文件存到node服务器。使用formidable  。

通过npm安装:

npm install formidable@latest

使用它进行文件转存,保存到临时目录得到文件信息。

再通过文件包重组。进行上传。注意此处上传必须遵循w3c上传文件表单标准,具体自己查资料。

其实思路很简单,但是实际操作起来还是挺麻烦,我中间也趟了好多坑,也是自己node不成熟,毕竟只是用来做中转!

直接上代码吧:看代码还是清晰:

server.js,用于启动服务并转发。

var http = require("http");
var url = require("url");
var fs = require('fs');
const querystring = require("querystring");
var path = require('path');
var formidable = require('formidable'),
  os = require('os'),
  util = require('util');
var config = require('./config').types; //
var netServerUrlFlag = require('./config').netServerUrlFlag;
var netServerhost = require('./config').netServerhost;
var netServerport = require('./config').netServerport;
var javaServerUrlFlag = require('./config').javaServerUrlFlag;
var javaServerhost = require('./config').javaServerhost;
var javaServerport = require('./config').javaServerport;
var fileServerUrlFlag = require('./config').fileServerUrlFlag;
var webapp = require('./config').webapp;
var PORT = require('./config').webport;
/**
 * 上传文件
 * @param files   经过formidable处理过的文件
 * @param req    httpRequest对象
 * @param postData  额外提交的数据
 */
function uploadFile(files, req, postData) {
  var boundaryKey = Math.random().toString(16);
  var endData = '\r\n----' + boundaryKey + '--';
  var filesLength = 0, content;
  // 初始数据,把post过来的数据都携带上去
  content = (function (obj) {
    var rslt = [];
    Object.keys(obj).forEach(function (key) {
      arr = ['\r\n----' + boundaryKey + '\r\n'];
      arr.push('Content-Disposition: form-data; name="' + obj[key][0] + '"\r\n\r\n');
      arr.push(obj[key][1]);
      rslt.push(arr.join(''));
    });
    return rslt.join('');
  })(postData); 
  // 组装数据
  Object.keys(files).forEach(function (key) {
    if (!files.hasOwnProperty(key)) {
      delete files.key;
      return;
    }
    content += '\r\n----' + boundaryKey + '\r\n' +
      'Content-Type: application/octet-stream\r\n' +
      'Content-Disposition: form-data; name="' + files[key][0] + '"; ' +
      'filename="' + files[key][1].name + '"; \r\n' +
      'Content-Transfer-Encoding: binary\r\n\r\n';
    files[key].contentBinary = new Buffer(content, 'utf-8');;
    filesLength += files[key].contentBinary.length + fs.statSync(files[key][1].path).size;
  });
  req.setHeader('Content-Type', 'multipart/form-data; boundary=--' + boundaryKey);
  req.setHeader('Content-Length', filesLength + Buffer.byteLength(endData));
  // 执行上传
  var allFiles = Object.keys(files);
  var fileNum = allFiles.length;
  var uploadedCount = 0;
  allFiles.forEach(function (key) {
    req.write(files[key].contentBinary);
    console.log("files[key].path:" + files[key][1].path);
    var fileStream = fs.createReadStream(files[key][1].path, { bufferSize: 4 * 1024 });
    fileStream.on('end', function () {
      // 上传成功一个文件之后,把临时文件删了
      fs.unlink(files[key][1].path);
      uploadedCount++;
      if (uploadedCount == fileNum) {
        // 如果已经是最后一个文件,那就正常结束
        req.end(endData);
      }
    });
    fileStream.pipe(req, { end: false });
  });
}
var server = http.createServer(function (request, response) {
  var clientUrl = request.url;
  var url_parts = url.parse(clientUrl); //解析路径
  var pathname = url_parts.pathname;
  var sreq = request;
  var sres = response;
  // .net 转发请求
  if (pathname.match(netServerUrlFlag) != null) {
    var clientUrl2 = clientUrl.replace("/" + netServerUrlFlag, '');
    console.log(".net转发请求......" + clientUrl2);
    var pramsJson = '';
    sreq.on("data", function (data) {
      pramsJson += data;
    }).on("end", function () {
      var contenttype = request.headers['content-type'];
      if (contenttype == undefined || contenttype == null || contenttype == '') {
        var opt = {
          host: netServerhost, //跨域访问的主机ip
          port: netServerport,
          path: clientUrl2,
          method: request.method,
          headers: {
            'Content-Length': Buffer.byteLength(pramsJson)
          }
        }
      } else {
        var opt = {
          host: netServerhost, //跨域访问的主机ip
          port: netServerport,
          path: clientUrl2,
          method: request.method,
          headers: {
            'Content-Type': request.headers['content-type'],
            'Content-Length': Buffer.byteLength(pramsJson)
          }
        }
      }
      console.log('method', opt.method);
      var body = '';
      var req = http.request(opt, function (res) {
        res.on('data', function (data) {
          body += data;
        }).on('end', function () {
          response.write(body);
          response.end();
        });
      }).on('error', function (e) {
        response.end('内部错误,请联系管理员!MSG:' + e);
        console.log("error: " + e.message);
      })
      req.write(pramsJson);
      req.end();
    })
  } else
    // java 转发请求
    if (pathname.match(javaServerUrlFlag) != null) {
      response.setHeader("Content-type", "text/plain;charset=UTF-8");
      var clientUrl2 = clientUrl.replace("/" + javaServerUrlFlag, '');
      console.log(".java转发请求......http://" + javaServerhost + ":" + javaServerport + "" + clientUrl2);
      var prams = '';
      sreq.on("data", function (data) {
        prams += data;
      }).on("end", function () {
        console.log("client pramsJson>>>>>" + prams);
        const postData = prams;
        console.log("client pramsJson>>>>>" + postData);
        var contenttype = request.headers['content-type'];
        if (contenttype == undefined || contenttype == null || contenttype == '') {
          var opt = {
            host: javaServerhost, //跨域访问的主机ip
            port: javaServerport,
            path: "/hrrp" + clientUrl2,
            method: request.method,
            headers: {
              'Content-Length': Buffer.byteLength(postData)
            }
          }
        } else {
          var opt = {
            host: javaServerhost, //跨域访问的主机ip
            port: javaServerport,
            path: "/hrrp" + clientUrl2,
            method: request.method,
            headers: {
              'Content-Type': request.headers['content-type'],
              'Content-Length': Buffer.byteLength(postData)
            }
          }
        }
        var body = '';
        console.log('method', opt.method);
        var req = http.request(opt, function (res) {
          //console.log("response: " + res.statusCode);
          res.on('data', function (data) {
            body += data;
          }).on('end', function () {
            response.write(body);
            response.end();
            //console.log("end:>>>>>>>" + body);
          });
        }).on('error', function (e) {
          response.end('内部错误,请联系管理员!MSG:' + e);
          console.log("error: " + e.message);
        })
        req.write(postData);
        req.end();
      })
    } else if (pathname.match(fileServerUrlFlag) != null) {
      //文件拦截保存到本地
      var form = new formidable.IncomingForm(),
        files = [],
        fields = [];
      form.uploadDir = os.tmpdir();
      form.on('field', function (field, value) {
        console.log(field, value);
        fields.push([field, value]);
      }).on('file', function (field, file) {
        console.log(field, file);
        files.push([field, file]);
      }).on('end', function () {
        //
        var clientUrl2 = clientUrl.replace("/" + fileServerUrlFlag, '');
        var opt = {
          host: netServerhost, //跨域访问的主机ip
          port: netServerport,
          path: clientUrl2,
          method: request.method
        }
        var body = '';
        var req = http.request(opt, function (res) {
          res.on('data', function (data) {
            body += data;
          }).on('end', function () {
            response.write(body);
            response.end();
          });
        }).on('error', function (e) {
          response.end('内部错误,请联系管理员!MSG:' + e);
          console.log("error: " + e.message);
        })
        //文件上传
        uploadFile(files, req, fields);
      });
      form.parse(sreq);
    }
    else {
      var realPath = path.join(webapp, pathname); //这里设置自己的文件名称;
      var ext = path.extname(realPath);
      ext = ext ? ext.slice(1) : 'unknown';
      fs.exists(realPath, function (exists) {
        //console.log("file is exists:"+exists+" file path: " + realPath + "");
        if (!exists) {
          response.writeHead(404, {
            'Content-Type': 'text/plain'
          });
          response.write("This request URL " + pathname + " was not found on this server.");
          response.end();
        } else {
          fs.readFile(realPath, "binary", function (err, file) {
            if (err) {
              response.writeHead(500, {
                'Content-Type': 'text/plain'
              });
              //response.end(err);
              response.end("内部错误,请联系管理员");
            } else {
              var contentType = config[ext] || "text/plain";
              response.writeHead(200, {
                'Content-Type': contentType
              });
              response.write(file, "binary");
              response.end();
            }
          });
        }
      });
    }
});
server.listen(PORT);
console.log("Server runing at port: " + PORT + ".");

config.js,用于配置。

exports.types = {
 "css": "text/css",
 "gif": "image/gif",
 "html": "text/html",
 "htm": "text/html",
 "ico": "image/x-icon",
 "jpeg": "image/jpeg",
 "jpg": "image/jpeg",
 "js": "text/javascript",
 "json": "application/json",
 "pdf": "application/pdf",
 "png": "image/png",
 "svg": "image/svg+xml",
 "swf": "application/x-shockwave-flash",
 "tiff": "image/tiff",
 "txt": "text/plain",
 "wav": "audio/x-wav",
 "wma": "audio/x-ms-wma",
 "wmv": "video/x-ms-wmv",
 "xml": "text/xml"
};
exports.netServerUrlFlag = "NETSERVER";
exports.netServerhost = "";
exports.netServerport = "";
exports.javaServerUrlFlag = "JAVASERVER";
exports.javaServerhost = ""; //转发的地址
exports.javaServerport = "";//转发的端口
exports.fileServerUrlFlag="FileUpload";
exports.webapp = "public";//项目目录
exports.webport = "82"; //项目启动端口

总结

以上所述是小编给大家介绍的Node做中转服务器转发接口,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
修复IE9&safari 的sort方法
Oct 21 Javascript
解析javascript 浏览器关闭事件
Jul 08 Javascript
类似php的js数组的in_array函数自定义方法
Dec 27 Javascript
解析jQuery的三种bind/One/Live事件绑定使用方法
Dec 30 Javascript
jQuery使用append在html元素后同时添加多项内容的方法
Mar 26 Javascript
7个有用的jQuery代码片段分享
May 19 Javascript
简介JavaScript中Boolean.toSource()方法的使用
Jun 05 Javascript
Javascript HTML5 Canvas实现的一个画板
Apr 12 Javascript
谈谈Vue.js——vue-resource全攻略
Jan 16 Javascript
对于js垃圾回收机制的理解
Sep 14 Javascript
详解Vue.js和layui日期控件冲突问题解决办法
Jul 25 Javascript
JavaScript高级程序设计之基本引用类型
Nov 17 Javascript
Vue组件之Tooltip的示例代码
Oct 18 #Javascript
JS正则表达式完美实现身份证校验功能
Oct 18 #Javascript
详解vue项目首页加载速度优化
Oct 18 #Javascript
JS简单实现滑动加载数据的方法示例
Oct 18 #Javascript
详解cordova打包成webapp的方法
Oct 18 #Javascript
prototype.js简单实现ajax功能示例
Oct 18 #Javascript
浅谈JS函数节流防抖
Oct 18 #Javascript
You might like
PHP获取php,mysql,apche的版本信息示例代码
2014/01/16 PHP
在win系统安装配置 Memcached for PHP 5.3 图文教程
2015/03/03 PHP
基于jquery的获取浏览器窗口大小的代码
2011/03/28 Javascript
关于js中for in的缺陷浅析
2013/12/02 Javascript
jquery实现勾选复选框触发事件给input赋值
2015/02/01 Javascript
理解jquery事件冒泡
2016/01/03 Javascript
js事件冒泡、事件捕获和阻止默认事件详解
2016/08/04 Javascript
基于JS快速实现导航下拉菜单动画效果附源码下载
2016/10/27 Javascript
jquery拼接ajax 的json和字符串拼接的方法
2017/03/11 Javascript
angular.js指令中transclude选项及ng-transclude指令详解
2017/05/24 Javascript
jQuery实现frame之间互通的方法
2017/06/26 jQuery
bootstrap multiselect下拉列表功能
2017/08/22 Javascript
100行代码实现一个vue分页组功能
2018/11/06 Javascript
利用node 判断打开的是文件 还是 文件夹的实例
2019/06/10 Javascript
Vue中util的工具函数实例详解
2019/07/08 Javascript
js回调函数仿360开机
2019/12/26 Javascript
JS异步宏队列与微队列原理区别详解
2020/07/02 Javascript
[40:16]TFT vs Mski Supermajor小组赛C组 BO3 第二场 6.3
2018/06/04 DOTA
用Python实现服务器中只重载被修改的进程的方法
2015/04/30 Python
详谈python中冒号与逗号的区别
2018/04/18 Python
python获取命令行输入参数列表的实例代码
2018/06/23 Python
深入理解Python 多线程
2020/06/16 Python
css3图片边框border-image的用法
2017/06/30 HTML / CSS
Wiggle中国:英国骑行、跑步、游泳 & 铁三运动装备专卖网店
2016/08/02 全球购物
18-35岁旅游团的全球领导者:Contiki
2017/02/08 全球购物
建筑设计师岗位职责
2013/11/18 职场文书
应届毕业生求职信
2013/11/30 职场文书
中国梦的演讲稿
2014/01/08 职场文书
新任教师自我鉴定
2014/02/24 职场文书
勾股定理课后反思
2014/04/26 职场文书
安全保卫工作竞聘材料
2014/08/25 职场文书
会计主管竞聘书
2015/09/15 职场文书
2019年教师入党申请书
2019/06/27 职场文书
2019年市场部个人述职报告(三篇)
2019/10/23 职场文书
Python 数据可视化之Seaborn详解
2021/11/02 Python
Ruby处理YAML和json数据
2022/04/18 Ruby