@@ -36,6 +36,7 @@ const Fs = require('fs');
3636const Events = require ( 'events' ) ;
3737const Crypto = require ( 'crypto' ) ;
3838const Zlib = require ( 'zlib' ) ;
39+ const Tls = require ( 'tls' ) ;
3940
4041const CONCAT = [ null , null ] ;
4142const COMPARER = global . Intl ? global . Intl . Collator ( ) . compare : function ( a , b ) {
@@ -81,6 +82,8 @@ const CT = 'Content-Type';
8182const CRC32TABLE = '00000000,77073096,EE0E612C,990951BA,076DC419,706AF48F,E963A535,9E6495A3,0EDB8832,79DCB8A4,E0D5E91E,97D2D988,09B64C2B,7EB17CBD,E7B82D07,90BF1D91,1DB71064,6AB020F2,F3B97148,84BE41DE,1ADAD47D,6DDDE4EB,F4D4B551,83D385C7,136C9856,646BA8C0,FD62F97A,8A65C9EC,14015C4F,63066CD9,FA0F3D63,8D080DF5,3B6E20C8,4C69105E,D56041E4,A2677172,3C03E4D1,4B04D447,D20D85FD,A50AB56B,35B5A8FA,42B2986C,DBBBC9D6,ACBCF940,32D86CE3,45DF5C75,DCD60DCF,ABD13D59,26D930AC,51DE003A,C8D75180,BFD06116,21B4F4B5,56B3C423,CFBA9599,B8BDA50F,2802B89E,5F058808,C60CD9B2,B10BE924,2F6F7C87,58684C11,C1611DAB,B6662D3D,76DC4190,01DB7106,98D220BC,EFD5102A,71B18589,06B6B51F,9FBFE4A5,E8B8D433,7807C9A2,0F00F934,9609A88E,E10E9818,7F6A0DBB,086D3D2D,91646C97,E6635C01,6B6B51F4,1C6C6162,856530D8,F262004E,6C0695ED,1B01A57B,8208F4C1,F50FC457,65B0D9C6,12B7E950,8BBEB8EA,FCB9887C,62DD1DDF,15DA2D49,8CD37CF3,FBD44C65,4DB26158,3AB551CE,A3BC0074,D4BB30E2,4ADFA541,3DD895D7,A4D1C46D,D3D6F4FB,4369E96A,346ED9FC,AD678846,DA60B8D0,44042D73,33031DE5,AA0A4C5F,DD0D7CC9,5005713C,270241AA,BE0B1010,C90C2086,5768B525,206F85B3,B966D409,CE61E49F,5EDEF90E,29D9C998,B0D09822,C7D7A8B4,59B33D17,2EB40D81,B7BD5C3B,C0BA6CAD,EDB88320,9ABFB3B6,03B6E20C,74B1D29A,EAD54739,9DD277AF,04DB2615,73DC1683,E3630B12,94643B84,0D6D6A3E,7A6A5AA8,E40ECF0B,9309FF9D,0A00AE27,7D079EB1,F00F9344,8708A3D2,1E01F268,6906C2FE,F762575D,806567CB,196C3671,6E6B06E7,FED41B76,89D32BE0,10DA7A5A,67DD4ACC,F9B9DF6F,8EBEEFF9,17B7BE43,60B08ED5,D6D6A3E8,A1D1937E,38D8C2C4,4FDFF252,D1BB67F1,A6BC5767,3FB506DD,48B2364B,D80D2BDA,AF0A1B4C,36034AF6,41047A60,DF60EFC3,A867DF55,316E8EEF,4669BE79,CB61B38C,BC66831A,256FD2A0,5268E236,CC0C7795,BB0B4703,220216B9,5505262F,C5BA3BBE,B2BD0B28,2BB45A92,5CB36A04,C2D7FFA7,B5D0CF31,2CD99E8B,5BDEAE1D,9B64C2B0,EC63F226,756AA39C,026D930A,9C0906A9,EB0E363F,72076785,05005713,95BF4A82,E2B87A14,7BB12BAE,0CB61B38,92D28E9B,E5D5BE0D,7CDCEFB7,0BDBDF21,86D3D2D4,F1D4E242,68DDB3F8,1FDA836E,81BE16CD,F6B9265B,6FB077E1,18B74777,88085AE6,FF0F6A70,66063BCA,11010B5C,8F659EFF,F862AE69,616BFFD3,166CCF45,A00AE278,D70DD2EE,4E048354,3903B3C2,A7672661,D06016F7,4969474D,3E6E77DB,AED16A4A,D9D65ADC,40DF0B66,37D83BF0,A9BCAE53,DEBB9EC5,47B2CF7F,30B5FFE9,BDBDF21C,CABAC28A,53B39330,24B4A3A6,BAD03605,CDD70693,54DE5729,23D967BF,B3667A2E,C4614AB8,5D681B02,2A6F2B94,B40BBE37,C30C8EA1,5A05DF1B,2D02EF8D' . split ( ',' ) . map ( s => parseInt ( s , 16 ) ) ;
8283const REGISARR = / \[ \d + \] $ / ;
8384const PROXYBLACKLIST = { 'localhost' : 1 , '127.0.0.1' : 1 , '0.0.0.0' : 1 } ;
85+ const PROXYOPTIONS = { } ;
86+ const PROXYHEADERS = { } ;
8487
8588exports . MONTHS = [ 'January' , 'February' , 'March' , 'April' , 'May' , 'June' , 'July' , 'August' , 'September' , 'October' , 'November' , 'December' ] ;
8689exports . DAYS = [ 'Sunday' , 'Monday' , 'Tuesday' , 'Wednesday' , 'Thursday' , 'Friday' , 'Saturday' ] ;
@@ -413,40 +416,19 @@ exports.keywords = function(content, forSearch, alternative, max_count, max_leng
413416} ;
414417
415418function parseProxy ( p ) {
416-
417419 var key = 'proxy_' + p ;
418-
419420 if ( F . temporary . other [ key ] )
420421 return F . temporary . other [ key ] ;
421422
422- var proxy = { } ;
423-
424- proxy . protocol = p . substring ( 0 , 7 ) ;
425-
426- if ( proxy . protocol === 'http://' ) {
427- proxy . protocol = 'http:' ;
428- p = p . substring ( 7 ) ;
429- } else if ( proxy . protocol === 'https:' ) {
430- proxy . protocol = 'https:' ;
431- p = p . substring ( 8 ) ;
432- } else
433- proxy . protocol = 'http:' ;
423+ if ( p . indexOf ( '://' ) === - 1 )
424+ p = 'http://' + p ;
434425
435- var index = p . indexOf ( '@' ) ;
436- if ( index !== - 1 ) {
437- // auth
438- var t = p . substring ( 0 , index ) . split ( ':' ) ;
439- proxy . username = t [ 0 ] ;
440- proxy . password = t [ 1 ] ;
441- p = p . substring ( index + 1 ) ;
442- }
426+ var obj = Url . parse ( p ) ;
443427
444- index = p . lastIndexOf ( ':' ) ;
445- proxy . hostname = p . substring ( 0 , index ) ;
446- proxy . port = p . substring ( index + 1 ) ;
447- proxy . method = 'CONNECT' ;
428+ if ( obj . auth )
429+ obj . _auth = 'Basic ' + U . createBuffer ( obj . auth ) . toString ( 'base64' ) ;
448430
449- return F . temporary . other [ key ] = proxy ;
431+ return F . temporary . other [ key ] = obj ;
450432}
451433
452434/**
@@ -617,7 +599,6 @@ global.REQUEST = exports.request = function(url, flags, data, callback, cookies,
617599
618600 var uri = Url . parse ( url ) ;
619601 uri . method = method ;
620- // uri.agent = false;
621602 uri . headers = headers ;
622603 options . uri = uri ;
623604
@@ -626,7 +607,10 @@ global.REQUEST = exports.request = function(url, flags, data, callback, cookies,
626607
627608 if ( proxy ) {
628609 options . proxy = proxy ;
629- request_proxy ( options , request_call ) ;
610+ if ( uri . protocol === 'http:' )
611+ request_call ( uri , options ) ;
612+ else
613+ request_proxy ( options , request_call ) ;
630614 } else if ( options . resolve ) {
631615 exports . resolve ( url , function ( err , u ) {
632616 ! err && ( uri . host = u . host ) ;
@@ -640,14 +624,17 @@ global.REQUEST = exports.request = function(url, flags, data, callback, cookies,
640624
641625function request_proxy ( options , callback ) {
642626
627+ PROXYHEADERS . host = options . uri . hostname ;
628+
643629 var proxy = options . proxy ;
644- proxy . path = options . uri . hostname ;
645- proxy . headers = { host : options . uri . hostname } ;
630+ proxy . path = options . uri . hostname + ':443' ;
631+ proxy . headers = PROXYHEADERS ;
632+ proxy . method = 'CONNECT' ;
646633
647- if ( proxy . username && proxy . password )
648- proxy . headers . authorization = 'Basic ' + U . createBuffer ( proxy . username + ':' + proxy . password ) . toString ( 'base64' ) ;
634+ if ( proxy . _auth )
635+ proxy . headers [ 'Proxy-Authorization' ] = proxy . _auth ;
649636
650- var req = proxy . protocol === 'http:' ? Http . request ( proxy ) : Https . request ( proxy ) ;
637+ var req = Http . request ( proxy ) ;
651638
652639 req . on ( 'error' , function ( e ) {
653640 options . callback ( new Error ( 'Proxy error: ' + e . toString ( ) ) , '' , 0 , EMPTYOBJECT , proxy . hostname , EMPTYOBJECT ) ;
@@ -656,10 +643,17 @@ function request_proxy(options, callback) {
656643
657644 req . on ( 'connect' , function ( res , socket ) {
658645 if ( res . statusCode === 200 ) {
659- options . uri . agent = options . uri . protocol === 'http:' ? new Http . Agent ( ) : new Https . Agent ( ) ;
660- options . uri . agent . reuseSocket ( socket , req ) ;
661- options . socket = socket ;
662- callback ( options . uri , options ) ;
646+ var tls = Tls . connect ( 0 , { servername : options . uri . hostname , headers : options . uri . headers , socket : socket } ) ;
647+
648+ tls . on ( 'secureConnect' , function ( ) {
649+ options . uri . agent = options . uri . protocol === 'http:' ? new Http . Agent ( ) : new Https . Agent ( ) ;
650+ options . uri . agent . reuseSocket ( tls , req ) ;
651+ //req.onSocket(tls);
652+ options . socket = tls ;
653+ options . proxy . tls = tls ;
654+ callback ( options . uri , options ) ;
655+ } ) ;
656+
663657 } else {
664658 options . callback ( new Error ( ( res . statusMessage || 'Proxy error' ) + ': ' + res . statusCode ) , '' , res . statusCode , res . headers , proxy . hostname , EMPTYOBJECT ) ;
665659 options . callback = null ;
@@ -672,7 +666,23 @@ function request_proxy(options, callback) {
672666function request_call ( uri , options ) {
673667
674668 var connection = uri . protocol === 'https:' ? Https : Http ;
675- var req = options . post ? connection . request ( uri , ( res ) => request_response ( res , uri , options ) ) : connection . get ( uri , ( res ) => request_response ( res , uri , options ) ) ;
669+ var opt ;
670+
671+ if ( options . proxy && ! options . proxy . tls ) {
672+ opt = PROXYOPTIONS ;
673+ opt . port = options . proxy . port ;
674+ opt . host = options . proxy . hostname ;
675+ opt . path = uri . href ;
676+ opt . headers = uri . headers ;
677+ opt . method = uri . method ;
678+
679+ if ( options . proxy . _auth )
680+ opt . headers [ 'Proxy-Authorization' ] = options . proxy . _auth ;
681+
682+ } else
683+ opt = uri ;
684+
685+ var req = options . post ? connection . request ( opt , ( res ) => request_response ( res , uri , options ) ) : connection . get ( opt , ( res ) => request_response ( res , uri , options ) ) ;
676686
677687 if ( ! options . callback ) {
678688 req . on ( 'error' , NOOP ) ;
@@ -702,7 +712,6 @@ function request_call(uri, options) {
702712 if ( options . upload ) {
703713 options . first = true ;
704714 options . files . wait ( function ( file , next ) {
705- // next();
706715 request_writefile ( req , options , file , next ) ;
707716 } , function ( ) {
708717
@@ -799,6 +808,13 @@ function request_response(res, uri, options) {
799808 res . req . removeAllListeners ( ) ;
800809 res . req = null ;
801810
811+ if ( options . proxy && tmp . protocol === 'https:' ) {
812+ // TLS?
813+ options . uri = tmp ;
814+ request_proxy ( options , request_call ) ;
815+ return
816+ }
817+
802818 if ( ! options . resolve ) {
803819 res . removeAllListeners ( ) ;
804820 res = null ;
@@ -1065,7 +1081,10 @@ exports.download = function(url, flags, data, callback, cookies, headers, encodi
10651081
10661082 if ( proxy ) {
10671083 options . proxy = proxy ;
1068- request_proxy ( options , download_call ) ;
1084+ if ( uri . protocol === 'http:' )
1085+ download_call ( uri , options ) ;
1086+ else
1087+ request_proxy ( options , download_call ) ;
10691088 } else if ( options . resolve ) {
10701089 exports . resolve ( url , function ( err , u ) {
10711090 ! err && ( uri . host = u . host ) ;
@@ -1079,32 +1098,46 @@ exports.download = function(url, flags, data, callback, cookies, headers, encodi
10791098
10801099function download_call ( uri , options ) {
10811100
1101+ var opt ;
10821102 options . length = 0 ;
10831103
1104+ if ( options . proxy && ! options . proxy . tls ) {
1105+ opt = PROXYOPTIONS ;
1106+ opt . port = options . proxy . port ;
1107+ opt . host = options . proxy . hostname ;
1108+ opt . path = uri . href ;
1109+ opt . headers = uri . headers ;
1110+ opt . method = uri . method ;
1111+
1112+ if ( options . proxy . _auth )
1113+ opt . headers [ 'Proxy-Authorization' ] = options . proxy . _auth ;
1114+ } else
1115+ opt = uri ;
1116+
10841117 var connection = uri . protocol === 'https:' ? Https : Http ;
1085- var req = options . post ? connection . request ( uri , ( res ) => download_response ( res , uri , options ) ) : connection . get ( uri , ( res ) => download_response ( res , uri , options ) ) ;
1118+ var req = options . post ? connection . request ( opt , ( res ) => download_response ( res , uri , options ) ) : connection . get ( opt , ( res ) => download_response ( res , uri , options ) ) ;
10861119
10871120 if ( ! options . callback ) {
10881121 req . on ( 'error' , NOOP ) ;
10891122 return ;
10901123 }
10911124
10921125 req . on ( 'error' , function ( err ) {
1093- if ( ! options . callback )
1094- return ;
1095- options . callback ( err ) ;
1096- options . callback = null ;
1097- options . evt . removeAllListeners ( ) ;
1098- options . evt = null ;
1126+ if ( options . callback ) {
1127+ options . callback ( err ) ;
1128+ options . callback = null ;
1129+ options . evt . removeAllListeners ( ) ;
1130+ options . evt = null ;
1131+ }
10991132 } ) ;
11001133
11011134 req . setTimeout ( options . timeout , function ( ) {
1102- if ( ! options . callback )
1103- return ;
1104- options . callback ( new Error ( exports . httpStatus ( 408 ) ) ) ;
1105- options . callback = null ;
1106- options . evt . removeAllListeners ( ) ;
1107- options . evt = null ;
1135+ if ( options . callback ) {
1136+ options . callback ( new Error ( exports . httpStatus ( 408 ) ) ) ;
1137+ options . callback = null ;
1138+ options . evt . removeAllListeners ( ) ;
1139+ options . evt = null ;
1140+ }
11081141 } ) ;
11091142
11101143 req . on ( 'response' , function ( response ) {
@@ -1141,6 +1174,13 @@ function download_response(res, uri, options) {
11411174 res . req . removeAllListeners ( ) ;
11421175 res . req = null ;
11431176
1177+ if ( options . proxy && tmp . protocol === 'https:' ) {
1178+ // TLS?
1179+ options . uri = tmp ;
1180+ download_call ( options , request_call ) ;
1181+ return
1182+ }
1183+
11441184 if ( ! options . resolve ) {
11451185 res . removeAllListeners ( ) ;
11461186 res = null ;
@@ -5877,5 +5917,31 @@ if (NODEVERSION > 699) {
58775917 exports . createBuffer = ( val , type ) => new Buffer ( val || '' , type ) ;
58785918}
58795919
5920+ function Callback ( count , callback ) {
5921+ this . pending = count ;
5922+ this . $callback = callback ;
5923+ }
5924+
5925+ Callback . prototype . done = function ( callback ) {
5926+ this . $callback = callback ;
5927+ return this ;
5928+ } ;
5929+
5930+ Callback . prototype . next = function ( ) {
5931+ var self = this ;
5932+ self . pending -- ;
5933+ if ( ! self . pending && self . $callback ) {
5934+ self . $callback ( ) ;
5935+ self . $callback = null ;
5936+ }
5937+ return self ;
5938+ } ;
5939+
5940+ global . Callback = Callback ;
5941+
5942+ exports . Callback = function ( count , callback ) {
5943+ return new Callback ( count , callback ) ;
5944+ } ;
5945+
58805946global . WAIT = exports . wait ;
58815947! global . F && require ( './index' ) ;
0 commit comments