Node做中转服务器,转发接口

2019年08月16日,建议使用nginx做转发。毕竟nginx更擅长。

转发代码段:

 1 server {
 2     listen       80;
 3     server_name   xxx.xxx.cn;
 4     location  ~* /eureka {
 5             rewrite /eureka/(.*) /$1 break;
 6             rewrite /eureka /$1 break;
 7             proxy_pass http://172.16.49.229:8001;
 8     }
 9     location  ~* /admin {
10             rewrite /admin/(.*) /$1 break;
11             rewrite /admin /$1 break;
12             proxy_pass http://172.16.49.229:8001;
13     }
14     location  ~* /crm {
15             rewrite /crm/(.*) /$1 break;
16             rewrite /crm /$1 break;
17             proxy_pass http://172.16.49.229:8001;
18     }
19     location  ~* /config-server {
20             rewrite /config-server/(.*) /$1 break;
21             rewrite /config-server /$1 break;
22             proxy_pass http://172.16.49.229:8001;
23     }
24 
25 }
View Code

2018年04月11日,转发修改。支持文件下载。

返回值处理代码修改!所有返回值以文件流的方式接收,支持附件下载和普通数据。你的框架要是可以直接访问访问文件服务器,那就直连了,要是像我一样,文件服务器在内网,只有前端服务器开了内网,那你就得和我一样,做文件下载转发,欢迎您,提供更好方案!

 1   var body = '';
 2             var req = http.request(opt, function (res) {
 3                 res.setEncoding('binary');  //二进制binary 
 4                 res.on('data', function (data) {
 5                     body += data;
 6                 }).on('end', function () {
 7                     response.writeHead(200, res.headers);
 8                     response.write(body, "binary");
 9                     response.end();
10                 });
11             }).on('error', function (e) {
12                 response.end('内部错误,请联系管理员!MSG:' + e);
13                 console.log("error: " + e.message);
14             })
View Code

查询各种资料,和整理网上一哥们不完整的接口。做成,可以使用的转发服务! 

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

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

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

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

通过npm安装:

npm install formidable@latest

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

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

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

  

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

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

  1 var http = require("http");
  2 var url = require("url");
  3 var fs = require('fs');
  4 const querystring = require("querystring");
  5 var path = require('path');
  6 var formidable = require('formidable'),
  7     os = require('os'),
  8     util = require('util');
  9 
 10 var config = require('./config').types; //
 11 
 12 var netServerUrlFlag = require('./config').netServerUrlFlag;
 13 var netServerhost = require('./config').netServerhost;
 14 var netServerport = require('./config').netServerport;
 15 
 16 var javaServerUrlFlag = require('./config').javaServerUrlFlag;
 17 var javaServerhost = require('./config').javaServerhost;
 18 var javaServerport = require('./config').javaServerport;
 19 
 20 var fileServerUrlFlag = require('./config').fileServerUrlFlag;
 21 
 22 var webapp = require('./config').webapp;
 23 var PORT = require('./config').webport;
 24 /**
 25  * 上传文件
 26  * @param files     经过formidable处理过的文件
 27  * @param req        httpRequest对象
 28  * @param postData    额外提交的数据
 29  */
 30 function uploadFile(files, req, postData) {
 31     var boundaryKey = Math.random().toString(16);
 32     var endData = '
----' + boundaryKey + '--';
 33     var filesLength = 0, content;
 34 
 35     // 初始数据,把post过来的数据都携带上去
 36     content = (function (obj) {
 37         var rslt = [];
 38         Object.keys(obj).forEach(function (key) {
 39             arr = ['
----' + boundaryKey + '
'];
 40             arr.push('Content-Disposition: form-data; name="' + obj[key][0] + '"

');
 41             arr.push(obj[key][1]);
 42             rslt.push(arr.join(''));
 43         });
 44         return rslt.join('');
 45     })(postData); 
 46 
 47     // 组装数据
 48     Object.keys(files).forEach(function (key) {
 49         if (!files.hasOwnProperty(key)) {
 50             delete files.key;
 51             return;
 52         }
 53         content += '
----' + boundaryKey + '
' +
 54             'Content-Type: application/octet-stream
' +
 55             'Content-Disposition: form-data; name="' + files[key][0] + '"; ' +
 56             'filename="' + files[key][1].name + '"; 
' +
 57             'Content-Transfer-Encoding: binary

';
 58         files[key].contentBinary = new Buffer(content, 'utf-8');;
 59         filesLength += files[key].contentBinary.length + fs.statSync(files[key][1].path).size;
 60     });
 61     req.setHeader('Content-Type', 'multipart/form-data; boundary=--' + boundaryKey);
 62     req.setHeader('Content-Length', filesLength + Buffer.byteLength(endData));
 63 
 64     // 执行上传
 65     var allFiles = Object.keys(files);
 66     var fileNum = allFiles.length;
 67     var uploadedCount = 0;
 68     allFiles.forEach(function (key) {
 69         req.write(files[key].contentBinary);
 70         console.log("files[key].path:" + files[key][1].path);
 71         var fileStream = fs.createReadStream(files[key][1].path, { bufferSize: 4 * 1024 });
 72         fileStream.on('end', function () {
 73             // 上传成功一个文件之后,把临时文件删了
 74             fs.unlink(files[key][1].path);
 75             uploadedCount++;
 76             if (uploadedCount == fileNum) {
 77                 // 如果已经是最后一个文件,那就正常结束
 78                 req.end(endData);
 79             }
 80         });
 81         fileStream.pipe(req, { end: false });
 82     });
 83 }
 84 var server = http.createServer(function (request, response) {
 85     var clientUrl = request.url;
 86     var url_parts = url.parse(clientUrl); //解析路径
 87     var pathname = url_parts.pathname;
 88 
 89     var sreq = request;
 90     var sres = response;
 91     // .net 转发请求
 92     if (pathname.match(netServerUrlFlag) != null) {
 93         var clientUrl2 = clientUrl.replace("/" + netServerUrlFlag, '');
 94         console.log(".net转发请求......" + clientUrl2);
 95         var pramsJson = '';
 96         sreq.on("data", function (data) {
 97             pramsJson += data;
 98         }).on("end", function () {
 99             var contenttype = request.headers['content-type'];
100             if (contenttype == undefined || contenttype == null || contenttype == '') {
101                 var opt = {
102                     host: netServerhost, //跨域访问的主机ip
103                     port: netServerport,
104                     path: clientUrl2,
105                     method: request.method,
106                     headers: {
107                         'Content-Length': Buffer.byteLength(pramsJson)
108                     }
109                 }
110             } else {
111                 var opt = {
112                     host: netServerhost, //跨域访问的主机ip
113                     port: netServerport,
114                     path: clientUrl2,
115                     method: request.method,
116                     headers: {
117                         'Content-Type': request.headers['content-type'],
118                         'Content-Length': Buffer.byteLength(pramsJson)
119                     }
120                 }
121             }
122             console.log('method', opt.method);
123 
124             var body = '';
125             var req = http.request(opt, function (res) {
126                 res.on('data', function (data) {
127                     body += data;
128                 }).on('end', function () {
129                     response.write(body);
130                     response.end();
131                 });
132             }).on('error', function (e) {
133                 response.end('内部错误,请联系管理员!MSG:' + e);
134                 console.log("error: " + e.message);
135             })
136             req.write(pramsJson);
137             req.end();
138         })
139 
140     } else
141         // java 转发请求
142         if (pathname.match(javaServerUrlFlag) != null) {
143             response.setHeader("Content-type", "text/plain;charset=UTF-8");
144 
145             var clientUrl2 = clientUrl.replace("/" + javaServerUrlFlag, '');
146             console.log(".java转发请求......http://" + javaServerhost + ":" + javaServerport + "" + clientUrl2);
147             var prams = '';
148             sreq.on("data", function (data) {
149                 prams += data;
150             }).on("end", function () {
151                 console.log("client pramsJson>>>>>" + prams);
152                 const postData = prams;
153                 console.log("client pramsJson>>>>>" + postData);
154                 var contenttype = request.headers['content-type'];
155                 if (contenttype == undefined || contenttype == null || contenttype == '') {
156                     var opt = {
157                         host: javaServerhost, //跨域访问的主机ip
158                         port: javaServerport,
159                         path: "/hrrp" + clientUrl2,
160                         method: request.method,
161                         headers: {
162                             'Content-Length': Buffer.byteLength(postData)
163                         }
164                     }
165                 } else {
166                     var opt = {
167                         host: javaServerhost, //跨域访问的主机ip
168                         port: javaServerport,
169                         path: "/hrrp" + clientUrl2,
170                         method: request.method,
171                         headers: {
172                             'Content-Type': request.headers['content-type'],
173                             'Content-Length': Buffer.byteLength(postData)
174                         }
175                     }
176                 }
177                 var body = '';
178 
179                 console.log('method', opt.method);
180                 var req = http.request(opt, function (res) {
181                     //console.log("response: " + res.statusCode);
182                     res.on('data', function (data) {
183                         body += data;
184                     }).on('end', function () {
185                         response.write(body);
186                         response.end();
187                         //console.log("end:>>>>>>>" + body);
188                     });
189                 }).on('error', function (e) {
190                     response.end('内部错误,请联系管理员!MSG:' + e);
191                     console.log("error: " + e.message);
192                 })
193 
194                 req.write(postData);
195                 req.end();
196 
197 
198             })
199         } else if (pathname.match(fileServerUrlFlag) != null) {
200             //文件拦截保存到本地
201             var form = new formidable.IncomingForm(),
202                 files = [],
203                 fields = [];
204             form.uploadDir = os.tmpdir();
205             form.on('field', function (field, value) {
206                 console.log(field, value);
207                 fields.push([field, value]);
208             }).on('file', function (field, file) {
209                 console.log(field, file);
210                 files.push([field, file]);
211             }).on('end', function () {
212                 //
213                 var clientUrl2 = clientUrl.replace("/" + fileServerUrlFlag, '');
214                 var opt = {
215                     host: netServerhost, //跨域访问的主机ip
216                     port: netServerport,
217                     path: clientUrl2,
218                     method: request.method
219                 }
220                 var body = '';
221                 var req = http.request(opt, function (res) {
222                     res.on('data', function (data) {
223                         body += data;
224                     }).on('end', function () {
225                         response.write(body);
226                         response.end();
227                     });
228                 }).on('error', function (e) {
229                     response.end('内部错误,请联系管理员!MSG:' + e);
230                     console.log("error: " + e.message);
231                 })
232                 //文件上传
233                 uploadFile(files, req, fields);
234             });
235             form.parse(sreq);
236         }
237         else {
238             var realPath = path.join(webapp, pathname); //这里设置自己的文件名称;
239             var ext = path.extname(realPath);
240             ext = ext ? ext.slice(1) : 'unknown';
241             fs.exists(realPath, function (exists) {
242                 //console.log("file is exists:"+exists+" file path: " + realPath + "");
243                 if (!exists) {
244                     response.writeHead(404, {
245                         'Content-Type': 'text/plain'
246                     });
247 
248                     response.write("This request URL " + pathname + " was not found on this server.");
249                     response.end();
250                 } else {
251                     fs.readFile(realPath, "binary", function (err, file) {
252                         if (err) {
253                             response.writeHead(500, {
254                                 'Content-Type': 'text/plain'
255                             });
256                             //response.end(err);
257                             response.end("内部错误,请联系管理员");
258                         } else {
259                             var contentType = config[ext] || "text/plain";
260                             response.writeHead(200, {
261                                 'Content-Type': contentType
262                             });
263                             response.write(file, "binary");
264                             response.end();
265                         }
266                     });
267                 }
268             });
269 
270         }
271 });
272 server.listen(PORT);
273 console.log("Server runing at port: " + PORT + ".");
View Code

config.js,用于配置。

 1 exports.types = {
 2   "css": "text/css",
 3   "gif": "image/gif",
 4   "html": "text/html",
 5   "htm": "text/html",
 6   "ico": "image/x-icon",
 7   "jpeg": "image/jpeg",
 8   "jpg": "image/jpeg",
 9   "js": "text/javascript",
10   "json": "application/json",
11   "pdf": "application/pdf",
12   "png": "image/png",
13   "svg": "image/svg+xml",
14   "swf": "application/x-shockwave-flash",
15   "tiff": "image/tiff",
16   "txt": "text/plain",
17   "wav": "audio/x-wav",
18   "wma": "audio/x-ms-wma",
19   "wmv": "video/x-ms-wmv",
20   "xml": "text/xml"
21 };
22 
23 exports.netServerUrlFlag = "NETSERVER";
24 exports.netServerhost = "";
25 exports.netServerport = "";
26 
27 exports.javaServerUrlFlag = "JAVASERVER";
28 exports.javaServerhost = ""; //转发的地址
29 exports.javaServerport = "";//转发的端口
30 
31 exports.fileServerUrlFlag="FileUpload";
32 exports.webapp = "public";//项目目录
33 
34 exports.webport = "82";  //项目启动端口
View Code

  

 
原文地址:https://www.cnblogs.com/shihaibin821/p/7683752.html