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 }
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 })
查询各种资料,和整理网上一哥们不完整的接口。做成,可以使用的转发服务!
由于项目在做前后端分离,牵扯跨域和夸协议问题,临时抱佛脚,选择用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 + ".");
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"; //项目启动端口