美文网首页
Node实现中转服务器

Node实现中转服务器

作者: Brandon_x | 来源:发表于2018-07-08 17:17 被阅读0次

    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, '');
    var prams = '';
          sreq.on("data", function (data) {
            prams += data;
          }).on("end", function () {
      const postData = prams;
    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 = '';
    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);
     })
            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) {
     fields.push([field, value]);
          }).on('file', function (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);
     })
            //文件上传
            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);
    }
    

    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实现中转服务器

          本文链接:https://www.haomeiwen.com/subject/erbouftx.html