实现代理设置proxy
用户在哪些情况下是需要设置网络代理呢?
1. 内网上不了外网,需要连接能上外网的内网电脑做代理,就能上外网;多个电脑共享上外网,就要用代理;
2.有些网页被封,通过国外的代理就能看到这被封的网站;
3.想隐藏真实IP;
4. 想加快访问网站速度,在网络出现拥挤或故障时,可通过代理服务器访问目的网站。比如A要访问C网站,但A到C网络出现问题,可以通过绕道,假设B是代理服务器,A可通过B, 再由B到C。
我们app的大多数用户情况是第一种.我们参考qq和chrome的插件switchysharp设置代理的方式来设计的界面
我们的项目是基于node-webkit技术进行开发的。
对于浏览器直接发送的请求设置代理可以直接设置chrome.proxy
1 if (proxy.proxyType == 0) {//不使用代理 2 chrome.proxy.settings.set({ 'value': { 'mode': 'direct' } }, function (e) { console.log(e) }); 3 } else if (proxy.proxyType == 1) {//使用http代理 4 chrome.proxy.settings.set({ 'value': { 'mode': 'fixed_servers', rules: { singleProxy: { scheme: 'http', host: proxy.host, port: proxy.port }, bypassList: null } } }, function (e) { console.log(e) }); 5 } else if (proxy.proxyType == 2) {//使用socks代理,可以支持版本4或者5 6 chrome.proxy.settings.set({ 'value': { 'mode': 'fixed_servers', rules: { singleProxy: { scheme: 'socks' + proxy.ver, host: proxy.host, port: proxy.port }, bypassList: null } } }, function (e) { console.log(e) }); 7 } else if (proxy.proxyType == 3) {//使用系统代理 8 chrome.proxy.settings.set({ 'value': { 'mode': 'system' } }, function (e) { console.log(e) });
而程序内部使用nodejs发送的请求需要在发送请求时通过option进行配置,才能走代理网络
1 var options = { 2 hostname: Common.Config.addrInfo.openApi, 3 path: '/api/Author/Article/Collected?skip=' + skip + ' & rows=' + this.pageSize, 4 method : "GET"; 5 headers: { 6 'Accept' : "application/json", 7 'Authorization': 'Bearer ' + index.userInfo.token 8 } 9 }; 10 11 var req = require('http').request(HttpUtil.setProxy(options), function (res) { 12 var err = HttpUtil.resStatus(options, res); 13 clearTimeout(timeoutEventId); 14 if (err) { 15 callback(err); 16 return; 17 } 18 var resData = []; 19 res.setEncoding('utf8'); 20 res.on('data', function (chunk) { 21 resData.push(chunk); 22 }).on("end", function () { 23 callback(null, resData.join("")); 24 }); 25 }); 26 req.on('error', function (e) { 27 clearTimeout(timeoutEventId); 28 callback(HttpUtil.reqStatus(options, e)); 29 req.end(); 30 }); 31 req.on('timeout', function (e) { 32 clearTimeout(timeoutEventId); 33 callback(HttpUtil.reqStatus(options, e)); 34 }); 35 req.end(); 36 } 37 static setProxy(options) {//设置代理信息 38 if (this.proxy) { 39 if (this.proxy.proxyType == 1 || (this.proxy.proxyType == 3 && this.proxy.host && this.proxy.sysProxyType == "PROXY")) { 40 options.path = "http://" + options.hostname + options.path; 41 options.hostname = null; 42 options.host = this.proxy.host; 43 options.port = this.proxy.port; 44 } else if (this.proxy.proxyType == 2 || (this.proxy.proxyType == 3 && this.proxy.host && this.proxy.sysProxyType == "SOCKS")) { 45 try { 46 if (!this.SocksProxyAgent) 47 this.SocksProxyAgent = require('socks-proxy-agent');//引用socks代理配置模块 48 } catch (e) { 49 this.SocksProxyAgent = null; 50 } 51 if (this.SocksProxyAgent) { 52 var agent = new this.SocksProxyAgent("socks" + this.proxy.ver + "://" + this.proxy.host + ":" + this.proxy.port); 53 options.agent = agent; 54 } 55 } 56 } 57 return options; 58 }
但是经过实践证明这个方法解决不了很多网络代理用户请求我们服务器接口失败的问题。
我们又找到了request模块,经过在有问题的电脑上进行测试这个模块是可以访问成功的。
1 var options1 = { 2 url: 'http://openapi.axeslide.com/api/TemplateTypes', 3 proxy: "http://10.22.138.21:8080", 4 headers: { 5 'User-Agent': 'request', 6 'Authorization': 'Bearer ' + index.userInfo.token, 7 'Accept' :"application/json" 8 } 9 }; 10 this.request.get(options1, function (error, response, body) { 11 if (!error && response.statusCode == 200) { 12 console.log(response,body,"ok") 13 } else { 14 console.log(response,error, "err") 15 } 16 })
但是不管是之前的方式还是现在的request模板,在使用socks代理时,接收的数据量超过一定值时返回就会出现问题,然后把之前的socks-proxy-agent
又换了socks5-http-client做测试解决了该问题。
现在说一下测试工具,fiddler和node搭建的socks代理服务器
fiddler相信对大家来对并不陌生,先打开fiddler options选项,然后配置下代理信息,主要是端口号,这里可以设置是否设置成系统代理,设置之后需要重新启动fiddler,如果浏览器配置成走9999 所有的请求fiddler都会抓取到。
搭建socks代理可以从网上找现成的代码,node搭建的。大家也可以下载 https://files.cnblogs.com/files/fangsmile/socks5.zip ,下载后运行node proxy
下面附一段switchysharp的实现代码:

1 ProxyPlugin.setProxy = function (proxyMode, proxyString, proxyExceptions, proxyConfigUrl) { 2 if (ProxyPlugin.disabled) return 0; 3 var config; 4 ProxyPlugin.proxyMode = Settings.setValue('proxyMode', proxyMode); 5 ProxyPlugin.proxyServer = Settings.setValue('proxyServer', proxyString); 6 ProxyPlugin.proxyExceptions = Settings.setValue('proxyExceptions', proxyExceptions); 7 ProxyPlugin.proxyConfigUrl = Settings.setValue('proxyConfigUrl', proxyConfigUrl); 8 switch (proxyMode) { 9 case 'system': 10 config = {mode:"system"}; 11 break; 12 case 'direct': 13 config = {mode:"direct"}; 14 break; 15 case 'manual': 16 var tmpbypassList = []; 17 var proxyExceptionsList = ProxyPlugin.proxyExceptions.split(';'); 18 var proxyExceptionListLength = proxyExceptionsList.length; 19 for (var i = 0; i < proxyExceptionListLength; i++) { 20 tmpbypassList.push(proxyExceptionsList[i].trim()) 21 } 22 proxyExceptionsList = null; 23 var profile = ProfileManager.parseProxyString(proxyString); 24 if (profile.useSameProxy) { 25 config = { 26 mode:"fixed_servers", 27 rules:{ 28 singleProxy:ProxyPlugin._parseProxy(profile.proxyHttp), 29 bypassList:tmpbypassList 30 } 31 }; 32 } 33 else { 34 var socksProxyString; 35 if (profile.proxySocks && !profile.proxyHttp && !profile.proxyFtp && !profile.proxyHttps) { 36 socksProxyString = profile.socksVersion == 4 ? 'socks=' + profile.proxySocks : 'socks5=' + profile.proxySocks; 37 config = { 38 mode:"fixed_servers", 39 rules:{ 40 singleProxy:ProxyPlugin._parseProxy(socksProxyString), 41 bypassList:tmpbypassList 42 } 43 } 44 45 } 46 else { 47 config = { 48 mode:"fixed_servers", 49 rules:{ 50 bypassList:tmpbypassList 51 } 52 }; 53 if (profile.proxySocks) { 54 socksProxyString = profile.socksVersion == 4 ? 'socks=' + profile.proxySocks : 'socks5=' + profile.proxySocks; 55 config.rules.fallbackProxy = ProxyPlugin._parseProxy(socksProxyString); 56 } 57 if (profile.proxyHttp) 58 config.rules.proxyForHttp = ProxyPlugin._parseProxy(profile.proxyHttp); 59 if (profile.proxyFtp) 60 config.rules.proxyForFtp = ProxyPlugin._parseProxy(profile.proxyFtp); 61 if (profile.proxyHttps) 62 config.rules.proxyForHttps = ProxyPlugin._parseProxy(profile.proxyHttps); 63 } 64 } 65 tmpbypassList = null; 66 break; 67 case 'auto': 68 if (ProxyPlugin.proxyConfigUrl == memoryPath) { 69 config = { 70 mode:"pac_script", 71 pacScript:{ 72 data:Settings.getValue('pacScriptData', '') 73 } 74 }; 75 Settings.setValue('pacScriptData', ''); 76 } 77 else { 78 config = { 79 mode:"pac_script", 80 pacScript:{ 81 url:ProxyPlugin.proxyConfigUrl 82 } 83 } 84 } 85 break; 86 } 87 ProxyPlugin.mute = true; 88 ProxyPlugin._proxy.settings.set({'value':config}, function () { 89 ProxyPlugin.mute = false; 90 if (ProxyPlugin.setProxyCallback != undefined) { 91 ProxyPlugin.setProxyCallback(); 92 ProxyPlugin.setProxyCallback = undefined; 93 } 94 }); 95 profile = null; 96 config = null; 97 return 0; 98 };
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?