@@ -21,72 +21,87 @@ pub enum AuthConfigError {
2121 ParseError ( #[ from] netrc:: Error ) ,
2222}
2323
24- #[ derive( Debug , Eq ) ]
24+ #[ derive( Debug , PartialEq , Eq ) ]
2525pub struct AuthUrl {
2626 schema : Option < String > ,
27- host_and_path : String ,
28- }
29-
30- impl AuthUrl {
31- fn drop_suffix ( & self ) -> & str {
32- let mut res = self . host_and_path . as_str ( ) ;
33-
34- while let Some ( x) = res. strip_suffix ( '/' ) {
35- res = x;
36- }
37-
38- res
39- }
27+ host : String ,
28+ port : Option < u16 > ,
29+ path : Option < String > ,
4030}
4131
4232impl From < & str > for AuthUrl {
4333 fn from ( value : & str ) -> Self {
44- if let Ok ( url) = Url :: parse ( value) {
45- AuthUrl {
46- schema : Some ( url. scheme ( ) . to_string ( ) ) ,
47- host_and_path : {
48- let mut s = String :: new ( ) ;
49- if let Some ( host) = url. host_str ( ) {
50- s. push_str ( host) ;
51- }
52- s. push_str ( url. path ( ) ) ;
53- s
54- } ,
55- }
56- } else {
57- AuthUrl {
58- schema : None ,
59- host_and_path : value. to_string ( ) ,
34+ // extract schema
35+ let ( schema, host_port_path) = value. split_once ( "://" ) . unzip ( ) ;
36+ let host_port_path = host_port_path. unwrap_or ( value) ;
37+
38+ // extract path
39+ let ( host_port, mut path) = host_port_path. split_once ( "/" ) . unzip ( ) ;
40+ let host_port = host_port. unwrap_or ( host_port_path) ;
41+
42+ // extract port
43+ let ( host, port) = host_port. split_once ( ":" ) . unzip ( ) ;
44+ let host = host. unwrap_or ( host_port) ;
45+ let ( host, port) = port
46+ . and_then ( |port| port. parse :: < u16 > ( ) . ok ( ) )
47+ . map ( |port| ( host, Some ( port) ) )
48+ . unwrap_or ( ( host_port, None ) ) ;
49+
50+ // strip suffix
51+ if let Some ( path) = & mut path {
52+ while let Some ( x) = path. strip_suffix ( '/' ) {
53+ * path = x;
6054 }
6155 }
56+
57+ Self {
58+ schema : schema. map ( |schema| schema. to_string ( ) ) ,
59+ host : host. to_string ( ) ,
60+ port,
61+ path : path. map ( |path| path. to_string ( ) ) ,
62+ }
6263 }
6364}
6465
6566impl From < & Url > for AuthUrl {
6667 fn from ( value : & Url ) -> Self {
67- let mut host_and_path = String :: new ( ) ;
68- let schema = value. scheme ( ) . to_string ( ) ;
69-
70- if let Some ( host) = value. host_str ( ) {
71- host_and_path. push_str ( host) ;
68+ let mut path = value. path ( ) ;
69+ while let Some ( x) = path. strip_suffix ( '/' ) {
70+ path = x;
7271 }
7372
74- host_and_path. push_str ( value. path ( ) ) ;
75-
7673 AuthUrl {
77- schema : Some ( schema) ,
78- host_and_path,
74+ schema : Some ( value. scheme ( ) . to_string ( ) ) ,
75+ host : value
76+ . host ( )
77+ . map ( |host| host. to_string ( ) )
78+ . unwrap_or_default ( ) ,
79+ port : value. port_or_known_default ( ) ,
80+ path : Some ( path. to_string ( ) ) ,
7981 }
8082 }
8183}
8284
83- impl PartialEq for AuthUrl {
84- fn eq ( & self , other : & Self ) -> bool {
85- if let Some ( ( a, b) ) = self . schema . as_ref ( ) . zip ( other. schema . as_ref ( ) ) {
86- return a == b && self . drop_suffix ( ) == other. drop_suffix ( ) ;
85+ impl AuthUrl {
86+ fn test ( & self , other : & Self ) -> bool {
87+ if let Some ( a) = & other. schema {
88+ if let Some ( b) = & self . schema {
89+ if a != b {
90+ return false ;
91+ }
92+ } else {
93+ if a != "https" && a != "tor+https" {
94+ return false ;
95+ }
96+ }
8797 }
88-
89- self . drop_suffix ( ) == other. drop_suffix ( )
98+ if self . port . is_some ( ) && other. port . is_some ( ) && self . port != other. port {
99+ return false ;
100+ }
101+ if self . path . is_some ( ) && other. path . is_some ( ) && self . path != other. path {
102+ return false ;
103+ }
104+ self . host == other. host
90105 }
91106}
92107
@@ -139,7 +154,91 @@ impl AuthConfig {
139154 pub fn find ( & self , url : & str ) -> Option < & Authenticator > {
140155 self . 0
141156 . iter ( )
142- . find ( |x| AuthUrl :: from ( url) == x . 0 )
157+ . find ( |( x , _ ) | x . test ( & AuthUrl :: from ( url) ) )
143158 . map ( |x| & x. 1 )
144159 }
145160}
161+
162+ #[ cfg( test) ]
163+ mod test {
164+ use crate :: * ;
165+
166+ #[ test]
167+ fn test_auth_parse ( ) {
168+ assert_eq ! (
169+ AuthUrl :: from( "localhost" ) ,
170+ AuthUrl {
171+ schema: None ,
172+ host: "localhost" . to_string( ) ,
173+ port: None ,
174+ path: None
175+ }
176+ ) ;
177+ assert_eq ! (
178+ AuthUrl :: from( "localhost:1234" ) ,
179+ AuthUrl {
180+ schema: None ,
181+ host: "localhost" . to_string( ) ,
182+ port: Some ( 1234 ) ,
183+ path: None
184+ }
185+ ) ;
186+ assert_eq ! (
187+ AuthUrl :: from( "ftp://localhost" ) ,
188+ AuthUrl {
189+ schema: Some ( "ftp" . to_string( ) ) ,
190+ host: "localhost" . to_string( ) ,
191+ port: None ,
192+ path: None
193+ }
194+ ) ;
195+ assert_eq ! (
196+ AuthUrl :: from( "ftp://localhost:123/something" ) ,
197+ AuthUrl {
198+ schema: Some ( "ftp" . to_string( ) ) ,
199+ host: "localhost" . to_string( ) ,
200+ port: Some ( 123 ) ,
201+ path: Some ( "something" . to_string( ) )
202+ }
203+ ) ;
204+ assert_eq ! (
205+ AuthUrl :: from( "ftp://localhost:123/something///" ) ,
206+ AuthUrl {
207+ schema: Some ( "ftp" . to_string( ) ) ,
208+ host: "localhost" . to_string( ) ,
209+ port: Some ( 123 ) ,
210+ path: Some ( "something" . to_string( ) )
211+ }
212+ ) ;
213+ }
214+
215+ #[ test]
216+ fn test_auth_match ( ) {
217+ assert ! ( AuthUrl :: from( "localhost" ) . test( & AuthUrl :: from( "localhost" ) ) ) ;
218+ assert ! ( !AuthUrl :: from( "localhost" ) . test( & AuthUrl :: from( "ten.avaj" ) ) ) ;
219+
220+ assert ! ( AuthUrl :: from( "localhost" ) . test( & AuthUrl :: from( "https://localhost" ) ) ) ;
221+ assert ! ( AuthUrl :: from( "https://localhost" ) . test( & AuthUrl :: from( "https://localhost" ) ) ) ;
222+ assert ! ( AuthUrl :: from( "localhost" ) . test( & AuthUrl :: from( "tor+https://localhost" ) ) ) ;
223+ assert ! ( !AuthUrl :: from( "localhost" )
224+ . test( & AuthUrl :: from( "aosctexttransferprotocol://localhost" ) ) ) ;
225+ assert ! ( AuthUrl :: from( "attp://localhost" ) . test( & AuthUrl :: from( "attp://localhost" ) ) ) ;
226+ assert ! ( !AuthUrl :: from( "attp://localhost" ) . test( & AuthUrl :: from( "http://localhost" ) ) ) ;
227+
228+ assert ! ( AuthUrl :: from( "localhost" ) . test( & AuthUrl :: from( "https://localhost:456" ) ) ) ;
229+ assert ! ( !AuthUrl :: from( "localhost:123" ) . test( & AuthUrl :: from( "https://localhost:456" ) ) ) ;
230+ assert ! ( AuthUrl :: from( "localhost:123" ) . test( & AuthUrl :: from( "https://localhost:123" ) ) ) ;
231+
232+ assert ! (
233+ AuthUrl :: from( "localhost:123/foo" ) . test( & AuthUrl :: from( "https://localhost:123/foo" ) )
234+ ) ;
235+ assert ! (
236+ AuthUrl :: from( "localhost:123/bar" ) . test( & AuthUrl :: from( "https://localhost:123/bar" ) )
237+ ) ;
238+ assert ! (
239+ !AuthUrl :: from( "localhost:123/foo" ) . test( & AuthUrl :: from( "https://localhost:123/bar" ) )
240+ ) ;
241+ assert ! ( AuthUrl :: from( "localhost:123" ) . test( & AuthUrl :: from( "https://localhost:123/bar" ) ) ) ;
242+ assert ! ( AuthUrl :: from( "localhost:123" ) . test( & AuthUrl :: from( "https://localhost:123/foo" ) ) ) ;
243+ }
244+ }
0 commit comments