@@ -8,6 +8,7 @@ use serde::Serialize;
88use serde_json:: Error ;
99
1010use crate :: protocol:: deserialize_u16_or_string;
11+ use crate :: protocol:: deserialize_from_string;
1112use crate :: protocol:: ProxyAdapter ;
1213use crate :: protocol:: UnsupportedLinkError ;
1314
@@ -22,9 +23,17 @@ pub struct Hysteria2 {
2223 pub ports : Option < String > ,
2324 #[ serde( skip_serializing_if = "Option::is_none" , rename = "hop-interval" ) ]
2425 pub hop_interval : Option < u16 > ,
25- #[ serde( skip_serializing_if = "Option::is_none" ) ]
26+ #[ serde(
27+ default ,
28+ skip_serializing_if = "Option::is_none" ,
29+ deserialize_with = "deserialize_from_string"
30+ ) ]
2631 pub up : Option < String > ,
27- #[ serde( skip_serializing_if = "Option::is_none" ) ]
32+ #[ serde(
33+ default ,
34+ skip_serializing_if = "Option::is_none" ,
35+ deserialize_with = "deserialize_from_string"
36+ ) ]
2837 pub down : Option < String > ,
2938 #[ serde( skip_serializing_if = "Option::is_none" ) ]
3039 pub obfs : Option < String > ,
@@ -62,7 +71,29 @@ impl ProxyAdapter for Hysteria2 {
6271 }
6372
6473 fn to_link ( & self ) -> String {
65- todo ! ( )
74+ let mut params = "insecure=" . to_string ( ) + if self . skip_cert_verify . unwrap_or ( false ) { "1" } else { "0" } ;
75+ if let Some ( sni) = & self . sni {
76+ params += & format ! ( "&sni={}" , urlencoding:: encode( sni) ) ;
77+ }
78+ if let Some ( obfs) = & self . obfs {
79+ params += & format ! ( "&obfs={}" , obfs) ;
80+ }
81+ if let Some ( obfs_password) = & self . obfs_password {
82+ params += & format ! ( "&obfs-password={}" , obfs_password) ;
83+ }
84+ if let Some ( ports) = & self . ports {
85+ params += & format ! ( "&mport={}" , ports) ;
86+ }
87+ if let Some ( up) = & self . up {
88+ params += & format ! ( "&up={}" , urlencoding:: encode( up) ) ;
89+ }
90+ if let Some ( down) = & self . down {
91+ params += & format ! ( "&down={}" , urlencoding:: encode( down) ) ;
92+ }
93+ if let Some ( alpn) = & self . alpn {
94+ params += & format ! ( "&alpn={}" , alpn. join( "," ) ) ;
95+ }
96+ format ! ( "hysteria2://{}@{}:{}/?{}#{}" , & self . password, & self . server, & self . port, & params, urlencoding:: encode( & self . name) )
6697 }
6798
6899 /*
@@ -102,6 +133,7 @@ impl ProxyAdapter for Hysteria2 {
102133 let sni = params_map. get ( "sni" ) . cloned ( ) ;
103134 let up = params_map. get ( "up" ) . cloned ( ) ;
104135 let down = params_map. get ( "down" ) . cloned ( ) ;
136+ let mut ports = params_map. get ( "mport" ) . cloned ( ) ;
105137 let mut alpn = None ;
106138 if let Some ( value) = params_map. get ( "alpn" ) . cloned ( ) {
107139 alpn = Some (
@@ -122,7 +154,6 @@ impl ProxyAdapter for Hysteria2 {
122154 let parts: Vec < & str > = parts[ 1 ] . split ( ":" ) . collect ( ) ;
123155 let server = String :: from ( parts[ 0 ] ) ;
124156 let port;
125- let mut ports = None ;
126157 match parts[ 1 ] . parse :: < u16 > ( ) {
127158 Ok ( p) => {
128159 port = p;
@@ -185,16 +216,37 @@ mod test {
185216 use super :: * ;
186217
187218 #[ test]
188- fn test_parse_vless ( ) {
219+ fn test_parse_hysteria2 ( ) {
189220 let link = String :: from ( "hysteria2://bfbe4deb-07c8-450b-945e-e3c7676ba5ed@163.123.192.167:50000/?insecure=1&sni=www.microsoft.com&mport=50000-50080#%E5%89%A9%E4%BD%99%E6%B5%81%E9%87%8F%EF%BC%9A163.97%20GB" ) ;
190- let hysteria2 = Hysteria2 :: from_link ( link) . unwrap ( ) ;
221+ let hysteria2 = Hysteria2 :: from_link ( link. clone ( ) ) . unwrap ( ) ;
191222 assert_eq ! ( hysteria2. server, "163.123.192.167" ) ;
192223 assert_eq ! ( hysteria2. port, 50000 ) ;
193224 assert_eq ! ( hysteria2. ports, Some ( "50000-50080" . to_string( ) ) ) ;
194225 assert_eq ! ( hysteria2. password, "bfbe4deb-07c8-450b-945e-e3c7676ba5ed" ) ;
195226 assert_eq ! ( hysteria2. sni, Some ( "www.microsoft.com" . to_string( ) ) ) ;
196227 assert_eq ! ( hysteria2. skip_cert_verify, Some ( true ) ) ;
197- assert_eq ! ( hysteria2. fingerprint, Some ( "chrome" . to_string( ) ) ) ;
198- println ! ( "{}" , hysteria2. to_json( ) . unwrap( ) ) ;
228+ assert_eq ! ( hysteria2. client_fingerprint, Some ( "chrome" . to_string( ) ) ) ;
229+ assert_eq ! ( hysteria2. to_link( ) , link) ;
230+ }
231+
232+ #[ test]
233+ fn test_hysteria2_from_json ( ) {
234+ let json = r#"{
235+ "auth": "836e5ec1-382f-4325-a1dd-e6b5cf2a3632",
236+ "name": "JP_01",
237+ "password": "836e5ec1-382f-4325-a1dd-e6b5cf2a3632",
238+ "port": 23030,
239+ "up": 100,
240+ "down": 100,
241+ "server": "tokyo2-500m.node.xn--l6qx3lcvp58x.com",
242+ "skip-cert-verify": true,
243+ "sni": "2.nodes.yljc.online",
244+ "type": "hysteria2",
245+ "udp": true
246+ }"# ;
247+
248+ let hysteria: Hysteria2 = serde_json:: from_str ( json) . unwrap ( ) ;
249+ assert_eq ! ( hysteria. name, "JP_01" ) ;
250+ assert_eq ! ( hysteria. up, Some ( "100" . to_string( ) ) )
199251 }
200252}
0 commit comments