├── .gitignore
├── LICENSE
├── README.md
├── index.js
└── package.json
/.gitignore:
--------------------------------------------------------------------------------
1 | lib-cov
2 | *.seed
3 | *.log
4 | *.csv
5 | *.dat
6 | *.out
7 | *.pid
8 | *.gz
9 |
10 | pids
11 | logs
12 | results
13 |
14 | npm-debug.log
15 | node_modules
16 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 unbug
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | logproxy
2 | ========
3 | Set up a proxy server to log http archives of your mobile devices.
4 |
5 |
6 |
7 | Install
8 | ========
9 | ```shell
10 | npm install -g logproxy
11 | ````
12 |
13 | Commands
14 | =========
15 | ```shell
16 | logproxy [listen port] [only log host,..]
17 | ```
18 |
19 | eg.
20 | =====
21 | 1.start logproxy with default setting
22 | ```shell
23 | logproxy
24 | ```
25 | 2.listen on port 8088 and only log hosts -- 'c.163.com' and every host matchs '126.com'
26 | ```shell
27 | logproxy 8088 c.163.com,*126.com
28 | ```
29 |
30 | Guide
31 | =========
32 | After run `logproxy`,you will see a log ` PROXY IS READY ON 192.168.1.102 PORT 1630`,set your device's http proxy to the IP address and port.
33 |
34 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /**
4 | * set up a proxy to log http archives
5 | * run:
6 | * node logproxy [listen port] [only log host,..]
7 | * eg.
8 | * 1.start logproxy with default setting
9 | * node logproxy
10 | * 2.listen on port 8088 and only log hosts -- 'c.163.com' and every host matchs '126.com'
11 | * node logproxy 8088 c.163.com,*126.com
12 | *
13 | * @auth http://www.iunbug.com
14 | */
15 | var http = require('http'),
16 | net = require('net'),
17 | fs = require('fs'),
18 | StringDecoder = require('string_decoder').StringDecoder,
19 | Buffer = require('buffer').Buffer,
20 | Iconv = require('iconv-lite'),//https://github.com/bnoordhuis/node-iconv,https://github.com/ashtuchkin/iconv-lite
21 | chardet = require('chardet'),//https://github.com/unbug/node-chardet
22 | colors = require('colors'),
23 | util = require('util');
24 |
25 | //prevent node.js from crashing
26 | process.on('uncaughtException', function (err) {
27 | console.log("process uncaughtException error");
28 | console.error(err);
29 | });
30 |
31 | var excuteArgvs = (function(){
32 | var p = process.argv[2] || 1630,
33 | f = process.argv[3]?process.argv[3].split(','):[];
34 | return {
35 | port: p,
36 | filterHosts: f
37 | }
38 | })();//end excuteArgvs
39 |
40 | function printLog(logs){
41 | logs = logs || 'NULL';
42 | if(typeof logs == 'string'){
43 | console.log(logs);
44 | }else{
45 | // console.log(util.inspect(logs, { showHidden: false, depth: null,colors: true}));
46 | console.dir(logs);
47 | }
48 | }//end printLog
49 | function getIPAddress() {
50 | var interfaces = require('os').networkInterfaces();
51 | for (var devName in interfaces) {
52 | var iface = interfaces[devName];
53 | for (var i = 0; i < iface.length; i++) {
54 | var alias = iface[i];
55 | if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal)
56 | return alias.address;
57 | }
58 | }
59 | return '0.0.0.0';
60 | }//end getIPAddress
61 |
62 | var formatHost = (function() {
63 | var reg = /^([^:]+)(:([0-9]+))?$/i;
64 | return function(host){
65 | var tmp = host.match(reg);
66 | return tmp?{host: tmp[1],port: tmp[3]}:{host: host}
67 | }
68 | })();//end formatHost
69 | var formatPath = (function() {
70 | var reg = /^[a-zA-Z]+:\/\/[^\/]+(\/.*)?$/i;
71 | return function(url){
72 | var tmp = url.match(reg);
73 | return tmp?(tmp[1].length>0&&tmp[1]):'/';
74 | }
75 | })();//end formatHost
76 | function decodeResponseBody(headers,body){
77 | var cs;
78 | cs = headers['content-type'].match(/.*charset=(.*)[;]?/i);
79 | cs = cs && cs[1];
80 | if(cs){
81 | console.log(('Body charset is '+cs ).magenta.bold);
82 | if(Iconv.encodingExists(cs)){
83 | return Iconv.decode(new Buffer(body),cs);
84 | }
85 | }
86 | return autoDecodeCharset(body);
87 | }//end decodeResponseBody
88 | function autoDecodeCharset(data){
89 | if(data){
90 | var buffer = new Buffer(data),
91 | charset = chardet.detect(buffer);
92 | console.log(('Data charset is '+charset ).magenta.bold);
93 | try {
94 | data = buffer.toString(charset);
95 | } catch (e) {
96 | if(Iconv.encodingExists(charset)){
97 | data = Iconv.decode(buffer,charset);
98 | }
99 | }
100 | return data;
101 | }
102 | }//end autoDecodeCharset
103 | /**
104 | *
105 | * @param {Object} log {reqMethod,reqUrl,reqHeaders,reqData,resCode,resHeaders,resBody}
106 | */
107 | var printClientLog = (function(){
108 | var requestCount = 0;
109 | return function(logs){
110 | if(!isFilterHost(logs.reqHeaders['host'])){return;}
111 |
112 | util.log(('--'+requestCount+'--------------------------- LOG REQUEST STARTED ---------------------------'+requestCount+'--').yellow);
113 |
114 | console.log('HTTP VERSION: '.magenta.bold+logs.httpVersion.red);
115 | console.log(('METHOD '+logs.reqMethod+': ').magenta.bold+logs.reqUrl.red);
116 | if( logs.resHeaders && (/image|audio|video|upload/ig).test(logs.resHeaders['content-type']) ){
117 | printLog('CONTENT TYPE: '.magenta.bold+logs.resHeaders['content-type'].red);
118 | }else{
119 | printLog('REQUEST HEADERS: '.magenta.bold);
120 | printLog(logs.reqHeaders);
121 | if( !(/connect/ig).test(logs.reqMethod) ){
122 | printLog('REQUEST DATA: '.magenta.bold);
123 | printLog(autoDecodeCharset(logs.reqData));
124 | printLog('RESPONSE STATUS CODE: '.magenta.bold+(logs.resCode+'').red);
125 | printLog('RESPONSE HEADERS: '.magenta.bold);
126 | printLog(logs.resHeaders);
127 | printLog('RESPONSE BODY: '.magenta.bold);
128 | printLog( autoDecodeCharset(logs.resBody) );
129 | }
130 | }
131 |
132 | util.log(('--'+requestCount+'----------------------------- LOG REQUEST END ---------------------------'+requestCount+'--').yellow);
133 |
134 | requestCount++;
135 | }
136 | })();//end printClientLog
137 | function isFilterHost(host){
138 | if(excuteArgvs.filterHosts.length<1 || host.length<1){
139 | return true;
140 | }
141 | for(var i=0;i