@@ -5,194 +5,194 @@ var http = require('http');
5
5
var url = require ( 'url' ) ;
6
6
7
7
function main ( ) {
8
- //convert `--key value` to cfg[key]=value
9
- var cfg = process . argv . slice ( 2 /*skip ["node", "xxx.js"]*/ ) . reduce ( function ( cfg , arg , i , argv ) {
10
- i % 2 === 0 && ( arg . slice ( 0 , 2 ) === '--' && ( cfg [ arg . slice ( 2 ) ] = argv [ i + 1 ] ) || arg . slice ( 0 , 1 ) === '-' && ( cfg [ arg . slice ( 1 ) ] = argv [ i + 1 ] ) ) ;
11
- return cfg ;
12
- } , /*init cfg:*/ { local_host : 'localhost' , local_port : 8080 , remote_host : 8080 } ) ;
13
- cfg . local_host = cfg . local_host || cfg . host ;
14
- cfg . local_port = Number ( cfg . local_port || cfg . port ) ;
15
- cfg . remote_port = Number ( cfg . remote_port ) ;
16
- cfg . as_pac_server = cfg . as_pac_server === 'true' ;
17
-
18
- if ( ! cfg . local_host || ! cfg . local_port || ! cfg . remote_host || ! cfg . usr || ! cfg . pwd )
19
- return console . error ( 'Usage of parameters:\n'
20
- + '\t-local_host host\t\t' + 'listening address. Default: localhost. (* means all interfaces)\n'
21
- + '\t-local_port port\t\t' + 'listening port. Default: 8080\n'
22
- + '\t-remote_host host\t\t' + 'real proxy server address\n'
23
- + '\t-remote_port port\t\t' + 'real proxy server port. Default: 8080\n'
24
- + '\t-usr user\t\t' + 'proxy user id\n'
25
- + '\t-pwd password\t\t' + 'proxy user password\n'
26
- + '\t-as_pac_server true or false \t\t' + 'used as pac(proxy auto configuration) server. Default: no\n'
27
- ) ;
28
- console . error ( 'Using parameters:\n' + JSON . stringify ( cfg , null , ' ' ) ) ;
29
- cfg . buf_proxy_basic_auth = new Buffer ( 'Proxy-Authorization: Basic ' + new Buffer ( cfg . usr + ':' + cfg . pwd ) . toString ( 'base64' ) ) ;
30
-
31
- if ( cfg . as_pac_server ) {
32
- createPacServer ( cfg . local_host , cfg . local_port , cfg . remote_host , cfg . remote_port , cfg . buf_proxy_basic_auth ) ;
33
- } else {
34
- createPortForwarder ( cfg . local_host , cfg . local_port , cfg . remote_host , cfg . remote_port , cfg . buf_proxy_basic_auth ) ;
35
- }
8
+ //convert `--key value` to cfg[key]=value
9
+ var cfg = process . argv . slice ( 2 /*skip ["node", "xxx.js"]*/ ) . reduce ( function ( cfg , arg , i , argv ) {
10
+ i % 2 === 0 && ( arg . slice ( 0 , 2 ) === '--' && ( cfg [ arg . slice ( 2 ) ] = argv [ i + 1 ] ) || arg . slice ( 0 , 1 ) === '-' && ( cfg [ arg . slice ( 1 ) ] = argv [ i + 1 ] ) ) ;
11
+ return cfg ;
12
+ } , /*init cfg:*/ { local_host : 'localhost' , local_port : 8080 , remote_host : 8080 } ) ;
13
+ cfg . local_host = cfg . local_host || cfg . host ;
14
+ cfg . local_port = Number ( cfg . local_port || cfg . port ) ;
15
+ cfg . remote_port = Number ( cfg . remote_port ) ;
16
+ cfg . as_pac_server = cfg . as_pac_server === 'true' ;
17
+
18
+ if ( ! cfg . local_host || ! cfg . local_port || ! cfg . remote_host || ! cfg . usr || ! cfg . pwd )
19
+ return console . error ( 'Usage of parameters:\n'
20
+ + '\t-local_host host\t\t' + 'listening address. Default: localhost. (* means all interfaces)\n'
21
+ + '\t-local_port port\t\t' + 'listening port. Default: 8080\n'
22
+ + '\t-remote_host host\t\t' + 'real proxy server address\n'
23
+ + '\t-remote_port port\t\t' + 'real proxy server port. Default: 8080\n'
24
+ + '\t-usr user\t\t' + 'proxy user id\n'
25
+ + '\t-pwd password\t\t' + 'proxy user password\n'
26
+ + '\t-as_pac_server true or false \t\t' + 'used as pac(proxy auto configuration) server. Default: no\n'
27
+ ) ;
28
+ console . error ( 'Using parameters:\n' + JSON . stringify ( cfg , null , ' ' ) ) ;
29
+ cfg . buf_proxy_basic_auth = new Buffer ( 'Proxy-Authorization: Basic ' + new Buffer ( cfg . usr + ':' + cfg . pwd ) . toString ( 'base64' ) ) ;
30
+
31
+ if ( cfg . as_pac_server ) {
32
+ createPacServer ( cfg . local_host , cfg . local_port , cfg . remote_host , cfg . remote_port , cfg . buf_proxy_basic_auth ) ;
33
+ } else {
34
+ createPortForwarder ( cfg . local_host , cfg . local_port , cfg . remote_host , cfg . remote_port , cfg . buf_proxy_basic_auth ) ;
35
+ }
36
36
}
37
37
38
38
var CR = 0xd , LF = 0xa , BUF_CR = new Buffer ( [ 0xd ] ) , BUF_CR_LF_CR_LF = new Buffer ( [ 0xd , 0xa , 0xd , 0xa ] ) , BUF_LF_LF = new Buffer ( [ 0xa , 0xa ] ) ;
39
39
var STATE_NONE = 0 , STATE_FOUND_LF = 1 , STATE_FOUND_LF_CR = 2 ;
40
40
41
41
function createPortForwarder ( local_host , local_port , remote_host , remote_port , buf_proxy_basic_auth ) {
42
- net . createServer ( { allowHalfOpen : true } , function ( socket ) {
43
- var realCon = net . connect ( { port : remote_port , host : remote_host , allowHalfOpen : true } ) ;
44
- realCon . on ( 'data' , function ( buf ) {
45
- //console.log('<<<<' + (Date.t=new Date()) + '.' + Date.t.getMilliseconds() + '\n' + buf.toString('ascii'));
46
- socket . write ( buf ) ;
47
- } ) . on ( 'end' , function ( ) {
48
- socket . end ( ) ;
49
- } ) . on ( 'close' , function ( ) {
50
- socket . end ( ) ;
51
- } ) . on ( 'error' , dummy ) ;
52
-
53
- var parser = new HTTPParser ( HTTPParser . REQUEST ) ;
54
- parser [ HTTPParser . kOnHeadersComplete ] = function ( ) {
55
- //console.log('---- kOnHeadersComplete----');
56
- //console.log(arguments);
57
- parser . __is_headers_complete = true ;
58
- } ;
59
- //parser[HTTPParser.kOnMessageComplete] = function () {
60
- // console.log('---- kOnMessageComplete----');
61
- // console.log(arguments);
62
- //};
63
-
64
- var state = STATE_NONE ;
65
-
66
- socket . on ( 'data' , function ( buf ) {
67
- //console.log('[' + remote_host + ':' + remote_port + ']>>>>' + (Date.t = new Date()) + '.' + Date.t.getMilliseconds() + '\n' + buf.toString('ascii'));
68
- //var ret = parser.execute(buf);
69
- //console.log('\n\n----parser result: ' + ret + ' buf len:' + buf.length);
70
- //realCon.write(buf);
71
- //return;
72
-
73
- var buf_ary = [ ] , unsavedStart = 0 , buf_len = buf . length ;
74
-
75
- //process orphan CR
76
- if ( state === STATE_FOUND_LF_CR && buf [ 0 ] !== LF ) {
77
- parser . execute ( BUF_CR ) ;
78
- buf_ary . push ( BUF_CR ) ;
79
- }
80
-
81
- for ( var i = 0 ; i < buf_len ; i ++ ) {
82
- //find first LF
83
- if ( state === STATE_NONE ) {
84
- if ( buf [ i ] === LF ) {
85
- state = STATE_FOUND_LF ;
86
- }
87
- continue ;
88
- }
89
-
90
- //find second CR LF or LF
91
- if ( buf [ i ] === LF ) {
92
- parser . __is_headers_complete = false ;
93
- parser . execute ( buf . slice ( unsavedStart , i + 1 ) ) ;
94
-
95
- if ( parser . __is_headers_complete ) {
96
- buf_ary . push ( buf . slice ( unsavedStart , buf [ i - 1 ] === CR ? i - 1 : i ) ) ;
97
- //console.log('insert auth header');
98
- buf_ary . push ( buf_proxy_basic_auth ) ;
99
- buf_ary . push ( state === STATE_FOUND_LF_CR ? BUF_CR_LF_CR_LF : BUF_LF_LF ) ;
100
-
101
- unsavedStart = i + 1 ;
102
- state = STATE_NONE ;
103
- }
104
- else {
105
- state = STATE_FOUND_LF ;
106
- }
107
- }
108
- else if ( buf [ i ] === CR && state === STATE_FOUND_LF ) {
109
- state = STATE_FOUND_LF_CR ;
110
- } else {
111
- state = STATE_NONE ;
112
- }
113
- }
114
-
115
- if ( unsavedStart < buf_len ) {
116
- //strip last CR if found LF_CR
117
- buf = buf . slice ( unsavedStart , state === STATE_FOUND_LF_CR ? buf_len - 1 : buf_len ) ;
118
- if ( buf . length ) {
119
- parser . execute ( buf ) ;
120
- buf_ary . push ( buf ) ;
121
- }
122
- }
123
-
124
- buf = Buffer . concat ( buf_ary ) ;
125
- realCon . write ( buf ) ;
126
-
127
- } ) . on ( 'end' , cleanup ) . on ( 'close' , cleanup ) . on ( 'error' , dummy ) ;
128
-
129
- function cleanup ( ) {
130
- if ( parser ) {
131
- parser . close ( ) ;
132
- parser = null ;
133
- }
134
- realCon . end ( ) ;
42
+ net . createServer ( { allowHalfOpen : true } , function ( socket ) {
43
+ var realCon = net . connect ( { port : remote_port , host : remote_host , allowHalfOpen : true } ) ;
44
+ realCon . on ( 'data' , function ( buf ) {
45
+ //console.log('<<<<' + (Date.t=new Date()) + '.' + Date.t.getMilliseconds() + '\n' + buf.toString('ascii'));
46
+ socket . write ( buf ) ;
47
+ } ) . on ( 'end' , function ( ) {
48
+ socket . end ( ) ;
49
+ } ) . on ( 'close' , function ( ) {
50
+ socket . end ( ) ;
51
+ } ) . on ( 'error' , dummy ) ;
52
+
53
+ var parser = new HTTPParser ( HTTPParser . REQUEST ) ;
54
+ parser [ HTTPParser . kOnHeadersComplete ] = function ( ) {
55
+ //console.log('---- kOnHeadersComplete----');
56
+ //console.log(arguments);
57
+ parser . __is_headers_complete = true ;
58
+ } ;
59
+ //parser[HTTPParser.kOnMessageComplete] = function () {
60
+ // console.log('---- kOnMessageComplete----');
61
+ // console.log(arguments);
62
+ //};
63
+
64
+ var state = STATE_NONE ;
65
+
66
+ socket . on ( 'data' , function ( buf ) {
67
+ //console.log('[' + remote_host + ':' + remote_port + ']>>>>' + (Date.t = new Date()) + '.' + Date.t.getMilliseconds() + '\n' + buf.toString('ascii'));
68
+ //var ret = parser.execute(buf);
69
+ //console.log('\n\n----parser result: ' + ret + ' buf len:' + buf.length);
70
+ //realCon.write(buf);
71
+ //return;
72
+
73
+ var buf_ary = [ ] , unsavedStart = 0 , buf_len = buf . length ;
74
+
75
+ //process orphan CR
76
+ if ( state === STATE_FOUND_LF_CR && buf [ 0 ] !== LF ) {
77
+ parser . execute ( BUF_CR ) ;
78
+ buf_ary . push ( BUF_CR ) ;
79
+ }
80
+
81
+ for ( var i = 0 ; i < buf_len ; i ++ ) {
82
+ //find first LF
83
+ if ( state === STATE_NONE ) {
84
+ if ( buf [ i ] === LF ) {
85
+ state = STATE_FOUND_LF ;
86
+ }
87
+ continue ;
135
88
}
136
- } ) . on ( 'error' , function ( err ) {
137
- console . log ( 'Failed to listen at ' + local_host + ':' + local_port + '\n' + err ) ;
138
- process . exit ( 1 ) ;
139
- } ) . listen ( local_port , local_host === '*' ? undefined : local_host , function ( ) {
140
- console . log ( 'OK: forward ' + local_host + ':' + local_port + ' to ' + remote_host + ':' + remote_port ) ;
141
- } ) ;
89
+
90
+ //find second CR LF or LF
91
+ if ( buf [ i ] === LF ) {
92
+ parser . __is_headers_complete = false ;
93
+ parser . execute ( buf . slice ( unsavedStart , i + 1 ) ) ;
94
+
95
+ if ( parser . __is_headers_complete ) {
96
+ buf_ary . push ( buf . slice ( unsavedStart , buf [ i - 1 ] === CR ? i - 1 : i ) ) ;
97
+ //console.log('insert auth header');
98
+ buf_ary . push ( buf_proxy_basic_auth ) ;
99
+ buf_ary . push ( state === STATE_FOUND_LF_CR ? BUF_CR_LF_CR_LF : BUF_LF_LF ) ;
100
+
101
+ unsavedStart = i + 1 ;
102
+ state = STATE_NONE ;
103
+ }
104
+ else {
105
+ state = STATE_FOUND_LF ;
106
+ }
107
+ }
108
+ else if ( buf [ i ] === CR && state === STATE_FOUND_LF ) {
109
+ state = STATE_FOUND_LF_CR ;
110
+ } else {
111
+ state = STATE_NONE ;
112
+ }
113
+ }
114
+
115
+ if ( unsavedStart < buf_len ) {
116
+ //strip last CR if found LF_CR
117
+ buf = buf . slice ( unsavedStart , state === STATE_FOUND_LF_CR ? buf_len - 1 : buf_len ) ;
118
+ if ( buf . length ) {
119
+ parser . execute ( buf ) ;
120
+ buf_ary . push ( buf ) ;
121
+ }
122
+ }
123
+
124
+ buf = Buffer . concat ( buf_ary ) ;
125
+ realCon . write ( buf ) ;
126
+
127
+ } ) . on ( 'end' , cleanup ) . on ( 'close' , cleanup ) . on ( 'error' , dummy ) ;
128
+
129
+ function cleanup ( ) {
130
+ if ( parser ) {
131
+ parser . close ( ) ;
132
+ parser = null ;
133
+ }
134
+ realCon . end ( ) ;
135
+ }
136
+ } ) . on ( 'error' , function ( err ) {
137
+ console . log ( 'Failed to listen at ' + local_host + ':' + local_port + '\n' + err ) ;
138
+ process . exit ( 1 ) ;
139
+ } ) . listen ( local_port , local_host === '*' ? undefined : local_host , function ( ) {
140
+ console . log ( 'OK: forward ' + local_host + ':' + local_port + ' to ' + remote_host + ':' + remote_port ) ;
141
+ } ) ;
142
142
}
143
143
144
144
var proxyAddrMap = { } ;
145
145
146
146
function createPacServer ( local_host , local_port , remote_host , remote_port , buf_proxy_basic_auth ) {
147
- http . createServer ( function ( req , res ) {
148
-
149
- var internal_req = url . parse ( req . url ) ;
150
-
151
- internal_req . host = remote_host ;
152
- internal_req . port = remote_port ;
153
- internal_req . headers = req . headers ;
154
- internal_req . keepAlive = req . headers [ 'connection' ] === 'keep-alive' ;
155
-
156
- http . get ( internal_req , function ( internal_res ) {
157
-
158
- delete internal_res . headers [ 'content-length' ] ;
159
- delete internal_res . headers [ 'transfer-encoding' ] ;
160
-
161
- res . writeHead ( internal_res . statusCode , internal_res . headers ) ;
162
-
163
- var buf_ary = [ ] ;
164
- internal_res . on ( 'data' , function ( buf ) {
165
- // console.log('<<<<' + (Date.t=new Date()) + '.' + Date.t.getMilliseconds() + '\n' + buf.toString('ascii'));
166
- buf_ary . push ( buf ) ;
167
- } ) . on ( 'end' , function ( ) {
168
- var s = Buffer . concat ( buf_ary ) . toString ( ) ;
169
- buf_ary = [ ] ;
170
- s = s . replace ( / \b P R O X Y \s + ( [ ^ ' " : ; \s ] + ) : ( \d + ) / g, function ( _ , host , port ) {
171
- var remoteAddr = host + ':' + port ;
172
- var _local_port = proxyAddrMap [ remoteAddr ] ;
173
- if ( ! _local_port ) {
174
- _local_port = local_port + Object . keys ( proxyAddrMap ) . length + 1 ;
175
- proxyAddrMap [ remoteAddr ] = _local_port ;
176
- createPortForwarder ( local_host , _local_port , host , Number ( port ) , buf_proxy_basic_auth ) ;
177
- }
178
-
179
- if ( local_host === '*' || local_host === '0.0.0.0' || local_host === '::' ) {
180
- return 'PROXY localhost:' + _local_port ;
181
- } else {
182
- return 'PROXY ' + local_host + ':' + _local_port ;
183
- }
184
- } ) ;
185
- //console.log('return patched pac');
186
- res . end ( s ) ;
187
- } ) . on ( 'error' , dummy ) ;
147
+ http . createServer ( function ( req , res ) {
148
+
149
+ var internal_req = url . parse ( req . url ) ;
150
+
151
+ internal_req . host = remote_host ;
152
+ internal_req . port = remote_port ;
153
+ internal_req . headers = req . headers ;
154
+ internal_req . keepAlive = req . headers [ 'connection' ] === 'keep-alive' ;
155
+
156
+ http . get ( internal_req , function ( internal_res ) {
157
+
158
+ delete internal_res . headers [ 'content-length' ] ;
159
+ delete internal_res . headers [ 'transfer-encoding' ] ;
160
+
161
+ res . writeHead ( internal_res . statusCode , internal_res . headers ) ;
162
+
163
+ var buf_ary = [ ] ;
164
+ internal_res . on ( 'data' , function ( buf ) {
165
+ // console.log('<<<<' + (Date.t=new Date()) + '.' + Date.t.getMilliseconds() + '\n' + buf.toString('ascii'));
166
+ buf_ary . push ( buf ) ;
167
+ } ) . on ( 'end' , function ( ) {
168
+ var s = Buffer . concat ( buf_ary ) . toString ( ) ;
169
+ buf_ary = [ ] ;
170
+ s = s . replace ( / \b P R O X Y \s + ( [ ^ ' " : ; \s ] + ) : ( \d + ) / g, function ( _ , host , port ) {
171
+ var remoteAddr = host + ':' + port ;
172
+ var _local_port = proxyAddrMap [ remoteAddr ] ;
173
+ if ( ! _local_port ) {
174
+ _local_port = local_port + Object . keys ( proxyAddrMap ) . length + 1 ;
175
+ proxyAddrMap [ remoteAddr ] = _local_port ;
176
+ createPortForwarder ( local_host , _local_port , host , Number ( port ) , buf_proxy_basic_auth ) ;
177
+ }
178
+
179
+ if ( local_host === '*' || local_host === '0.0.0.0' || local_host === '::' ) {
180
+ return 'PROXY localhost:' + _local_port ;
181
+ } else {
182
+ return 'PROXY ' + local_host + ':' + _local_port ;
183
+ }
188
184
} ) ;
189
- res . on ( 'error' , dummy ) ;
190
- } ) . on ( 'error' , function ( err ) {
191
- console . log ( 'Failed to listen at ' + local_host + ':' + local_port + '\n' + err ) ;
192
- process . exit ( 1 ) ;
193
- } ) . listen ( local_port , local_host === '*' ? undefined : local_host , function ( ) {
194
- console . log ( 'OK: listen at ' + local_host + ':' + local_port ) ;
185
+ //console.log('return patched pac');
186
+ res . end ( s ) ;
187
+ } ) . on ( 'error' , dummy ) ;
195
188
} ) ;
189
+ res . on ( 'error' , dummy ) ;
190
+ } ) . on ( 'error' , function ( err ) {
191
+ console . log ( 'Failed to listen at ' + local_host + ':' + local_port + '\n' + err ) ;
192
+ process . exit ( 1 ) ;
193
+ } ) . listen ( local_port , local_host === '*' ? undefined : local_host , function ( ) {
194
+ console . log ( 'OK: listen at ' + local_host + ':' + local_port ) ;
195
+ } ) ;
196
196
}
197
197
198
198
function dummy ( ) {
0 commit comments