77import { SocksProxyAgent } from 'socks-proxy-agent' ;
88
99async function proxyHttpRequest (
10- target : Pick < http . RequestOptions , 'hostname' | 'port' | 'agent' > ,
10+ target : Pick < http . RequestOptions , 'hostname' | 'port' > ,
1111 isHttps : boolean | undefined ,
1212 request : {
1313 path : string ;
@@ -16,53 +16,83 @@ async function proxyHttpRequest(
1616 body : string | undefined ;
1717 } ,
1818) : Promise < APIGatewayProxyResultV2 > {
19- return new Promise ( ( resolve , reject ) => {
20- const chunks : Buffer [ ] = [ ] ;
21- const httpLib = isHttps == undefined ?
22- ( target . port == 443 ? https : http ) :
23- ( isHttps ? https : http ) ;
24- const apiRequest = httpLib . request ( {
25- ...target ,
26- path : request . path ,
27- method : request . method ,
28- headers : request . headers ,
29- } , ( res : http . IncomingMessage ) => {
30- res . on ( 'data' , ( chunk : Buffer ) => {
31- chunks . push ( chunk ) ;
32- } ) ;
33- res . on ( 'end' , ( ) => {
34- const responseBody = Buffer . concat ( chunks ) ;
35- resolve ( {
36- statusCode : res . statusCode || 500 ,
37- headers : res . headers as Record < string , string > ,
38- body : responseBody . toString ( 'base64' ) ,
39- isBase64Encoded : true ,
19+
20+ async function requestPromise ( ) : Promise < APIGatewayProxyResultV2 > {
21+ const socksProxyAgent = new SocksProxyAgent ( 'socks://localhost:1055' ) ;
22+ return new Promise ( ( resolve , reject ) => {
23+ const chunks : Buffer [ ] = [ ] ;
24+ const httpLib = isHttps == undefined ?
25+ ( target . port == 443 ? https : http ) :
26+ ( isHttps ? https : http ) ;
27+ const apiRequest = httpLib . request ( {
28+ ...target ,
29+ agent : socksProxyAgent ,
30+ path : request . path ,
31+ method : request . method ,
32+ headers : request . headers ,
33+ } , ( res : http . IncomingMessage ) => {
34+ res . on ( 'data' , ( chunk : Buffer ) => {
35+ chunks . push ( chunk ) ;
36+ } ) ;
37+ res . on ( 'end' , ( ) => {
38+ const responseBody = Buffer . concat ( chunks ) ;
39+ resolve ( {
40+ statusCode : res . statusCode || 500 ,
41+ headers : res . headers as Record < string , string > ,
42+ body : responseBody . toString ( 'base64' ) ,
43+ isBase64Encoded : true ,
44+ } ) ;
45+ } ) ;
46+ res . on ( 'error' , ( error : Error ) : void => {
47+ console . error ( 'Error receiving response:' , error ) ;
48+ reject ( error ) ;
4049 } ) ;
4150 } ) ;
42- res . on ( 'error' , ( error : Error ) : void => {
43- console . error ( 'Error receiving response:' , error ) ;
51+
52+ apiRequest . on ( 'error' , ( error : Error ) : void => {
53+ console . error ( 'Error sending request:' , error ) ;
4454 reject ( error ) ;
4555 } ) ;
46- } ) ;
4756
48- apiRequest . on ( 'error' , ( error : Error ) : void => {
49- console . error ( 'Error sending request:' , error ) ;
50- reject ( error ) ;
57+ if ( request . body != null ) {
58+ apiRequest . write ( request . body ) ;
59+ }
60+ apiRequest . end ( ) ;
5161 } ) ;
62+ }
63+
5264
53- if ( request . body != null ) {
54- apiRequest . write ( request . body ) ;
65+ const connectionRetryDelays = [ 10 , 50 , 100 , 500 , 1000 , 2000 , 3000 ] ;
66+ let attempt = 0 ;
67+ let success = false ;
68+ let response : APIGatewayProxyResultV2 ;
69+
70+ do {
71+ try {
72+ response = await requestPromise ( ) ;
73+ success = true ;
74+ } catch ( error ) {
75+ if ( error == 'Error: Socks5 proxy rejected connection - Failure' && attempt < connectionRetryDelays . length ) {
76+ console . error ( 'Error: Socks5 proxy rejected connection - Failure' ) ;
77+ console . log ( 'Retrying in' , connectionRetryDelays [ attempt ] , 'ms' ) ;
78+ await new Promise ( ( resolve ) => setTimeout ( resolve , connectionRetryDelays [ attempt ] ) ) ;
79+ attempt ++ ;
80+ } else {
81+ throw error ;
82+ }
5583 }
56- apiRequest . end ( ) ;
57- } ) ;
84+ } while ( ! success && attempt < connectionRetryDelays . length ) ;
85+
86+ if ( attempt > 0 ) {
87+ console . log ( 'Error: Socks5 proxy rejected connection - Failure - RESOLVED - attempt:' , attempt , 'total delay time:' , connectionRetryDelays . slice ( 0 , attempt ) . reduce ( ( a , b ) => a + b , 0 ) ) ;
88+ }
89+
90+ return response ! ;
5891}
5992
6093export async function handler ( event : APIGatewayProxyEventV2 ) : Promise < APIGatewayProxyResultV2 > {
61-
6294 let metrics : Metrics | undefined ;
6395 try {
64- const socksProxyAgent = new SocksProxyAgent ( 'socks://localhost:1055' ) ;
65-
6696 let isHttps = undefined ; // Auto-detect, will be set for port 443
6797 if ( ! event . headers [ 'ts-target-ip' ] ) {
6898 return {
@@ -102,15 +132,13 @@ export async function handler(event: APIGatewayProxyEventV2): Promise<APIGateway
102132 const response = await proxyHttpRequest ( {
103133 hostname : event . headers [ 'ts-target-ip' ] ,
104134 port : event . headers [ 'ts-target-port' ] ,
105- agent : socksProxyAgent ,
106135 } , isHttps ,
107136 {
108137 path : event . requestContext . http . path ,
109138 headers : targetHeaders ,
110139 method : event . requestContext . http . method ,
111140 body : event . body ,
112- } ,
113- ) ;
141+ } ) ;
114142
115143 metrics ?. addMetric ( 'success' , MetricUnit . Count , 1 ) ;
116144 return response ;
0 commit comments