1
+ use async_trait:: async_trait;
2
+ use rustls:: pki_types:: ServerName ;
1
3
use std:: fmt:: { Display , Formatter } ;
2
4
use std:: net:: { IpAddr , SocketAddr } ;
3
5
use std:: str:: FromStr ;
4
6
5
- use async_trait:: async_trait;
6
- use rustls:: pki_types:: ServerName ;
7
-
8
7
use capybara_util:: cachestr:: Cachestr ;
9
8
10
9
use crate :: { CapybaraError , Result } ;
11
10
12
11
#[ derive( Clone , Hash , Eq , PartialEq ) ]
13
12
pub enum UpstreamKey {
14
- Tcp ( SocketAddr ) ,
15
- Tls ( SocketAddr , ServerName < ' static > ) ,
16
- TcpHP ( Cachestr , u16 ) ,
17
- TlsHP ( Cachestr , u16 , ServerName < ' static > ) ,
13
+ Tcp ( Addr ) ,
14
+ Tls ( Addr ) ,
18
15
Tag ( Cachestr ) ,
19
16
}
20
17
18
+ #[ derive( Clone , Hash , Eq , PartialEq ) ]
19
+ pub enum Addr {
20
+ SocketAddr ( SocketAddr ) ,
21
+ Host ( Cachestr , u16 ) ,
22
+ }
23
+
24
+ impl Addr {
25
+ fn parse_from ( s : & str , default_port : Option < u16 > ) -> Result < Self > {
26
+ let ( host, port) = host_and_port ( s) ?;
27
+
28
+ let port = match port {
29
+ None => {
30
+ default_port. ok_or_else ( || CapybaraError :: InvalidUpstream ( s. to_string ( ) . into ( ) ) ) ?
31
+ }
32
+ Some ( port) => port,
33
+ } ;
34
+
35
+ if let Ok ( addr) = host. parse :: < IpAddr > ( ) {
36
+ return Ok ( Addr :: SocketAddr ( SocketAddr :: new ( addr, port) ) ) ;
37
+ }
38
+
39
+ Ok ( Addr :: Host ( Cachestr :: from ( host) , port) )
40
+ }
41
+ }
42
+
43
+ impl Display for Addr {
44
+ fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
45
+ match self {
46
+ Addr :: SocketAddr ( addr) => write ! ( f, "{}" , addr) ,
47
+ Addr :: Host ( host, port) => write ! ( f, "{}:{}" , host, port) ,
48
+ }
49
+ }
50
+ }
51
+
52
+ #[ inline]
53
+ fn host_and_port ( s : & str ) -> Result < ( & str , Option < u16 > ) > {
54
+ let mut sp = s. splitn ( 2 , ':' ) ;
55
+
56
+ match sp. next ( ) {
57
+ None => Err ( CapybaraError :: InvalidUpstream ( s. to_string ( ) . into ( ) ) ) ,
58
+ Some ( first) => match sp. next ( ) {
59
+ Some ( second) => match second. parse :: < u16 > ( ) {
60
+ Ok ( port) => Ok ( ( first, Some ( port) ) ) ,
61
+ Err ( _) => Err ( CapybaraError :: InvalidUpstream ( s. to_string ( ) . into ( ) ) ) ,
62
+ } ,
63
+ None => Ok ( ( first, None ) ) ,
64
+ } ,
65
+ }
66
+ }
67
+
21
68
impl FromStr for UpstreamKey {
22
69
type Err = CapybaraError ;
23
70
@@ -31,29 +78,13 @@ impl FromStr for UpstreamKey {
31
78
port == 443
32
79
}
33
80
34
- fn host_and_port ( s : & str ) -> Result < ( & str , Option < u16 > ) > {
35
- let mut sp = s. splitn ( 2 , ':' ) ;
36
-
37
- match sp. next ( ) {
38
- None => Err ( CapybaraError :: InvalidUpstream ( s. to_string ( ) . into ( ) ) ) ,
39
- Some ( first) => match sp. next ( ) {
40
- Some ( second) => match second. parse :: < u16 > ( ) {
41
- Ok ( port) => Ok ( ( first, Some ( port) ) ) ,
42
- Err ( _) => Err ( CapybaraError :: InvalidUpstream ( s. to_string ( ) . into ( ) ) ) ,
43
- } ,
44
- None => Ok ( ( first, None ) ) ,
45
- } ,
46
- }
47
- }
48
-
49
81
fn to_sni ( sni : & str ) -> Result < ServerName < ' static > > {
50
82
ServerName :: try_from ( sni)
51
83
. map_err ( |_| CapybaraError :: InvalidTlsSni ( sni. to_string ( ) . into ( ) ) )
52
84
. map ( |it| it. to_owned ( ) )
53
85
}
54
86
55
87
// FIXME: too many duplicated codes
56
-
57
88
if let Some ( suffix) = s. strip_prefix ( "upstream://" ) {
58
89
return if suffix. is_empty ( ) {
59
90
Err ( CapybaraError :: InvalidUpstream ( s. to_string ( ) . into ( ) ) )
@@ -63,74 +94,42 @@ impl FromStr for UpstreamKey {
63
94
}
64
95
65
96
if let Some ( suffix) = s. strip_prefix ( "tcp://" ) {
66
- let ( host, port) = host_and_port ( suffix) ?;
67
- let port = port. ok_or_else ( || CapybaraError :: InvalidUpstream ( s. to_string ( ) . into ( ) ) ) ?;
68
- return Ok ( match host. parse :: < IpAddr > ( ) {
69
- Ok ( ip) => UpstreamKey :: Tcp ( SocketAddr :: new ( ip, port) ) ,
70
- Err ( _) => UpstreamKey :: TcpHP ( Cachestr :: from ( host) , port) ,
71
- } ) ;
97
+ let addr = Addr :: parse_from ( suffix, None ) ?;
98
+ return Ok ( UpstreamKey :: Tcp ( addr) ) ;
72
99
}
73
100
74
101
if let Some ( suffix) = s. strip_prefix ( "tls://" ) {
75
- let ( host, port) = host_and_port ( suffix) ?;
76
- let port = port. ok_or_else ( || CapybaraError :: InvalidUpstream ( s. to_string ( ) . into ( ) ) ) ?;
77
- return Ok ( match host. parse :: < IpAddr > ( ) {
78
- Ok ( ip) => {
79
- let server_name = ServerName :: from ( ip) ;
80
- UpstreamKey :: Tls ( SocketAddr :: new ( ip, port) , server_name)
81
- }
82
- Err ( _) => UpstreamKey :: TlsHP ( Cachestr :: from ( host) , port, to_sni ( host) ?) ,
83
- } ) ;
102
+ let addr = Addr :: parse_from ( suffix, Some ( 443 ) ) ?;
103
+ return Ok ( UpstreamKey :: Tls ( addr) ) ;
84
104
}
85
105
86
106
if let Some ( suffix) = s. strip_prefix ( "http://" ) {
87
- let ( host, port) = host_and_port ( suffix) ?;
88
- let port = port. unwrap_or ( 80 ) ;
89
- return Ok ( match host. parse :: < IpAddr > ( ) {
90
- Ok ( ip) => UpstreamKey :: Tcp ( SocketAddr :: new ( ip, port) ) ,
91
- Err ( _) => UpstreamKey :: TcpHP ( Cachestr :: from ( host) , port) ,
92
- } ) ;
107
+ let addr = Addr :: parse_from ( suffix, Some ( 80 ) ) ?;
108
+ return Ok ( UpstreamKey :: Tcp ( addr) ) ;
93
109
}
94
110
95
111
if let Some ( suffix) = s. strip_prefix ( "https://" ) {
96
- let ( host, port) = host_and_port ( suffix) ?;
97
- let port = port. unwrap_or ( 443 ) ;
98
- return Ok ( match host. parse :: < IpAddr > ( ) {
99
- Ok ( ip) => {
100
- let server_name = ServerName :: from ( ip) ;
101
- UpstreamKey :: Tls ( SocketAddr :: new ( ip, port) , server_name)
102
- }
103
- Err ( _) => UpstreamKey :: TlsHP ( Cachestr :: from ( host) , port, to_sni ( host) ?) ,
104
- } ) ;
112
+ let addr = Addr :: parse_from ( suffix, Some ( 443 ) ) ?;
113
+ return Ok ( UpstreamKey :: Tls ( addr) ) ;
105
114
}
106
115
107
116
let ( host, port) = host_and_port ( s) ?;
108
117
let port = port. ok_or_else ( || CapybaraError :: InvalidUpstream ( s. to_string ( ) . into ( ) ) ) ?;
109
- Ok ( match host. parse :: < IpAddr > ( ) {
110
- Ok ( ip) => UpstreamKey :: Tcp ( SocketAddr :: new ( ip, port) ) ,
111
- Err ( _) => UpstreamKey :: TcpHP ( Cachestr :: from ( host) , port) ,
112
- } )
118
+ let addr = match host. parse :: < IpAddr > ( ) {
119
+ Ok ( ip) => Addr :: SocketAddr ( SocketAddr :: new ( ip, port) ) ,
120
+ Err ( _) => Addr :: Host ( Cachestr :: from ( host) , port) ,
121
+ } ;
122
+
123
+ Ok ( UpstreamKey :: Tcp ( addr) )
113
124
}
114
125
}
115
126
116
127
impl Display for UpstreamKey {
117
128
fn fmt ( & self , f : & mut Formatter < ' _ > ) -> std:: fmt:: Result {
118
129
match self {
119
130
UpstreamKey :: Tcp ( addr) => write ! ( f, "tcp://{}" , addr) ,
120
- UpstreamKey :: Tls ( addr, sni) => {
121
- if let ServerName :: DnsName ( name) = sni {
122
- return write ! ( f, "tls://{}?sni={}" , addr, name. as_ref( ) ) ;
123
- }
124
- write ! ( f, "tls://{}" , addr)
125
- }
126
- UpstreamKey :: TcpHP ( addr, port) => write ! ( f, "tcp://{}:{}" , addr, port) ,
127
- UpstreamKey :: TlsHP ( addr, port, sni) => {
128
- if let ServerName :: DnsName ( name) = sni {
129
- return write ! ( f, "tls://{}:{}?sni={}" , addr, port, name. as_ref( ) ) ;
130
- }
131
- write ! ( f, "tls://{}:{}" , addr, port)
132
- }
133
- UpstreamKey :: Tag ( tag) => write ! ( f, "upstream://{}" , tag. as_ref( ) ) ,
131
+ UpstreamKey :: Tls ( addr) => write ! ( f, "tls://{}" , addr) ,
132
+ UpstreamKey :: Tag ( tag) => write ! ( f, "upstream://{}" , tag) ,
134
133
}
135
134
}
136
135
}
@@ -182,18 +181,12 @@ mod tests {
182
181
( "https://127.0.0.1:8443" , "tls://127.0.0.1:8443" ) ,
183
182
// schema+host
184
183
( "http://example.com" , "tcp://example.com:80" ) ,
185
- (
186
- "https://example.com" ,
187
- "tls://example.com:443?sni=example.com" ,
188
- ) ,
184
+ ( "https://example.com" , "tls://example.com:443" ) ,
189
185
// schema+host+port
190
186
( "tcp://localhost:8080" , "tcp://localhost:8080" ) ,
191
- ( "tls://localhost:8443" , "tls://localhost:8443?sni=localhost " ) ,
187
+ ( "tls://localhost:8443" , "tls://localhost:8443" ) ,
192
188
( "http://localhost:8080" , "tcp://localhost:8080" ) ,
193
- (
194
- "https://localhost:8443" ,
195
- "tls://localhost:8443?sni=localhost" ,
196
- ) ,
189
+ ( "https://localhost:8443" , "tls://localhost:8443" ) ,
197
190
] {
198
191
assert ! ( s. parse:: <UpstreamKey >( ) . is_ok_and( |it| {
199
192
let actual = it. to_string( ) ;
0 commit comments