1515use std:: { fmt, net:: IpAddr } ;
1616
1717use bytes:: Bytes ;
18- use http:: header:: HeaderValue ;
18+ use http:: { header:: HeaderValue , uri :: Authority } ;
1919use ipnet:: IpNet ;
2020use percent_encoding:: percent_decode_str;
2121
@@ -328,14 +328,16 @@ fn parse_env_uri(val: &str) -> Option<Intercept> {
328328 let uri = val. parse :: < http:: Uri > ( ) . ok ( ) ?;
329329 let mut builder = http:: Uri :: builder ( ) ;
330330 let mut is_httpish = false ;
331+ let mut is_socks = false ;
331332 let mut auth = Auth :: Empty ;
332333
333334 builder = builder. scheme ( match uri. scheme ( ) {
334335 Some ( s) => {
335336 if s == & http:: uri:: Scheme :: HTTP || s == & http:: uri:: Scheme :: HTTPS {
336337 is_httpish = true ;
337338 s. clone ( )
338- } else if s. as_str ( ) == "socks5" || s. as_str ( ) == "socks5h" {
339+ } else if matches ! ( s. as_str( ) , "socks4" | "socks4a" | "socks5" | "socks5h" ) {
340+ is_socks = true ;
339341 s. clone ( )
340342 } else {
341343 // can't use this proxy scheme
@@ -349,7 +351,13 @@ fn parse_env_uri(val: &str) -> Option<Intercept> {
349351 }
350352 } ) ;
351353
354+ // If the scheme is a SOCKS protocol and no port is specified, set the default port to 1080.
352355 let authority = uri. authority ( ) ?;
356+ let authority = if is_socks && authority. port ( ) . is_none ( ) {
357+ format ! ( "{authority}:1080" ) . parse :: < Authority > ( ) . ok ( ) ?
358+ } else {
359+ authority. clone ( )
360+ } ;
353361
354362 if let Some ( ( userinfo, host_port) ) = authority. as_str ( ) . split_once ( '@' ) {
355363 let ( user, pass) = userinfo. split_once ( ':' ) ?;
@@ -365,15 +373,15 @@ fn parse_env_uri(val: &str) -> Option<Intercept> {
365373 }
366374 builder = builder. authority ( host_port) ;
367375 } else {
368- builder = builder. authority ( authority. clone ( ) ) ;
376+ builder = builder. authority ( authority) ;
369377 }
370378
371379 // removing any path, but we MUST specify one or the builder errors
372380 builder = builder. path_and_query ( "/" ) ;
373381
374- let dst = builder. build ( ) . ok ( ) ?;
382+ let uri = builder. build ( ) . ok ( ) ?;
375383
376- Some ( Intercept { uri : dst , auth } )
384+ Some ( Intercept { uri, auth } )
377385}
378386
379387fn encode_basic_auth ( user : & str , pass : Option < & str > ) -> HeaderValue {
@@ -838,4 +846,25 @@ mod tests {
838846
839847 assert ! ( m. intercept( & "http://rick.roll" . parse( ) . unwrap( ) ) . is_none( ) ) ;
840848 }
849+
850+ fn test_parse_socks ( url : & str ) {
851+ let p = p ! {
852+ all = url,
853+ } ;
854+
855+ let proxy = intercept ( & p, "https://example.local" ) ;
856+ assert_eq ! ( proxy. uri( ) , url) ;
857+ }
858+
859+ #[ test]
860+ fn test_parse_socks4 ( ) {
861+ test_parse_socks ( "socks4://localhost:8887" ) ;
862+ test_parse_socks ( "socks4a://localhost:8887" ) ;
863+ }
864+
865+ #[ test]
866+ fn test_parse_socks5 ( ) {
867+ test_parse_socks ( "socks5://localhost:8887" ) ;
868+ test_parse_socks ( "socks5h://localhost:8887" ) ;
869+ }
841870}
0 commit comments