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 = '\r\n----' + 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 = ['\r\n----' + boundaryKey + '\r\n']; 40 arr.push('Content-Disposition: form-data; name="' + obj[key][0] + '"\r\n\r\n'); 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 += '\r\n----' + boundaryKey + '\r\n' + 54 'Content-Type: application/octet-stream\r\n' + 55 'Content-Disposition: form-data; name="' + files[key][0] + '"; ' + 56 'filename="' + files[key][1].name + '"; \r\n' + 57 'Content-Transfer-Encoding: binary\r\n\r\n'; 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"; //項目啟動端口