当前位置: 首页 > 后端技术 > Node.js

用node和express搭建的代理服务器(源码)

时间:2023-04-03 23:27:38 Node.js

示例git地址:https://github.com/xubaodian/...本例使用node和express搭建的代理服务器,预期目标如下:1、开通某服务A,可以实现普通restful请求、文件上传、静态资源访问等几个功能。2、开启节点代理服务B,指向服务A,访问代理服务B,访问服务A的任意功能。如下图:图中上半部分为直接访问服务,关闭-职责部分是通过代理服务器访问服务。使用代理服务器时,浏览器向代理服务器请求数据,代理服务器转发请求,并将接收到的数据返回给浏览器,即所有数据都通过代理服务器转发。带着这个目标,我们将描述如何实现这个功能。既然是request和response的转发,那我们先了解一下什么是request。请求和响应简介http请求和响应主要由消息头、空行和消息体三部分组成。我们不需要关心空行。其实对于我们来说,只要完成消息头和消息体的转发,代理功能就可以说是实现了。通过代理请求和响应的整个过程如下:1.代理服务器收到请求后,必须保留请求,然后返回目标服务数据给浏览器。2、提取请求路径、请求头、请求体等数据。3、以2中提取的数据为参数,向目标服务器发送请求。4、接收目标服务器返回的数据,提取响应头、响应体等数据。5、将4中提取的数据返回给客户端(浏览器)。6.断开连接。经过这些步骤,代理就实现了。代码实现下面直接上传代码,然后给出一些解释。代理函数如下:consthttp=require('http');constquerystring=require('querystring');//获取请求的cookie和query等letgetHeader=(reqClient)=>{letheaders=reqClient.headers;标头.path=reqClient.path;headers.query=reqClient.query;headers.cookie=reqClient.get('cookie')||'';returnheaders;}//代理函数,options为代理设置,包括目标服务器ip,端口等letproxy=(options)=>{letreqOptions={hostname:options.host,port:options.port}//返回请求处理函数,reqClient浏览器请求,resClient是响应浏览器返回函数的对象(reqClient,resClient){//设置目标服务器的请求参数,header中的参数letheaders=getHeader(reqClient);reqOptions.headers=reqClient.headers;让查询=[];如果(headers.query){Object.keys(headers.query).map(key=>{query.push(key+'='+headers.query[key]);});reqOptions.path=headers.path+(query.length===0?'':('?'+query.join('&')));}reqOptions.cookie=headers.cookie;reqOptions.method=reqClient.method;//向目标服务器发送请求,reqProxy是对目标服务器的请求,resProxy是目标服务器的响应letreqProxy=http.request(reqOptions,(resProxy)=>{resProxy.setEncoding('utf8');//设置返回的http头resClient.set(resProxy.headers);resClient.status(resProxy.statusCode);//接收目标服务器返回的数据resProxy.on('data',(chunk)=>{//从目标服务器接收数据后,将数据以流的形式返回给浏览器resClient.write(chunk);});//从目标服务器接收数据结束resProxy.on('end',()=>{//向浏览器写入数据结束。resClient.end();});//目标服务器响应错误resProxy.on('error',()=>{//响应错误,结束向浏览器返回数据resClient.end();});});//接收浏览器数据reqClient.on('data',(chunk)=>{//向目标服务器发送数据流reqProxy.write(chunk);});//接收数据结束reqClient.on('end',()=>{//向目标服务器写入数据结束reqProxy.end();});//普通JSON数据代理if(Object.keys(reqClient.body).length){reqProxy.write(querystring.stringify(reqClient.body));reqProxy.end();}}}module.exports=代理;以上就是节点代理的核心代码。支持普通请求、静态资源代理、文件上传下载代理等功能。Git地址:https://github.com/xubaodian/...在demo中,核心代码在common/proxy.js,我也实现了两个测试服务。server文件下的app.js和app2.js是两个服务的入口文件。app2.js是目标服务器,有3个测试页面1、http://localhost:20000/json.htmlpost请求测试,对应'/json'接口,可以发送数据,f12查看请求是否正常successful2、http://localhost:20000/upload.html文件上传测试,对应接口'/upload'接口,上传文件,f12查看请求是否成功,服务器upload文件夹下会有文件.3、http://localhost:20000/get.htmlget请求测试,对应接口'/get',f12也检查app2是目标服务器,有3个接口。1.'/upload'接口,测试文件上传功能,上传的文件会放在uploads文件夹,上传的文件,文件名是一个uuid,没有后缀,添加后缀检查文件是否完整。已经测试过了,传输1G的文件是没有问题的。我没有在更大的文件上尝试过。如果需要,可以尝试2.'/json'来测试POST请求。3.'/get',测试GET请求。app.js为代理服务器,监听端口为18000,所有请求都转发给app2,即在app中访问app2的所有接口静态资源都是一致的。测试步骤:1、打开目标服务器,通过三个页面即可测试功能。2、打开代理服务器,访问以下三个页面:http://localhost:18000/json.htmlhttp://localhost:18000/upload.htmlhttp://localhost:18000/get.html测试同样的功能.如果实现了与步骤1相同的功能,则代理服务功能已经实现。经测试,代理功能没有问题。如有任何疑问,请留言,或发送邮件至472784995@qq.com。至于性能,我没测试过,因为我自己的应用场景访问量不多,所以可以用。