0

0

Node做中转服务器,转发接口 - 石海斌

一个新手

一个新手

发布时间:2017-10-19 09:46:05

|

2019人浏览过

|

来源于php中文网

原创

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

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

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

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

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

通过npm安装:


npm install formidable@latest

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

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

Yodayo
Yodayo

一个专为动漫迷和vTuber打造的AI艺术创作平台、交流社区

下载

其实思路很简单,但是实际操作起来还是挺麻烦,我中间也趟了好多坑,也是自己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 + ".");

View Code

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";  //项目启动端口

 

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

76

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

38

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

83

2026.03.09

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

97

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

223

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

458

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

169

2026.03.04

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

246

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

34

2026.03.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
HTML5/CSS3/JavaScript/ES6入门课程
HTML5/CSS3/JavaScript/ES6入门课程

共102课时 | 7.3万人学习

前端基础到实战(HTML5+CSS3+ES6+NPM)
前端基础到实战(HTML5+CSS3+ES6+NPM)

共162课时 | 21.6万人学习

第二十二期_前端开发
第二十二期_前端开发

共119课时 | 13.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号