用戶在哪些情況下是需要設置網絡代理呢?
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搭建的。大家也可以下載 http://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 };