@@ -2,6 +2,7 @@ use std::convert::TryFrom;
2
2
use std:: hash:: { Hash , Hasher } ;
3
3
use std:: str:: FromStr ;
4
4
use std:: { cmp, fmt, str} ;
5
+ use std:: net:: { SocketAddr } ;
5
6
6
7
use bytes:: Bytes ;
7
8
@@ -50,6 +51,49 @@ impl Authority {
50
51
. expect ( "static str is not valid authority" )
51
52
}
52
53
54
+ /// Attempt to create an `Authority` from SockAddr
55
+ ///
56
+ /// This function will convert the IP address, scope and port number found
57
+ /// in a SockAddr into an appropriately formatted URI authority.
58
+ ///
59
+ /// This includes formatting the IPv4 or IPv6 into a string, adding the scope for IPv6 addresses,
60
+ /// enclosing it in [], and then adding any port number present.
61
+ ///
62
+ /// # Examples
63
+ ///
64
+ /// ```
65
+ /// # use http::uri::Authority;
66
+ /// let authority = Authority::from_static("example.com");
67
+ /// assert_eq!(authority.host(), "example.com");
68
+ /// ```
69
+ pub fn from_sockaddr ( sa : SocketAddr ) -> Result < Self , InvalidUri > {
70
+ let x: ByteStr = match sa {
71
+ SocketAddr :: V4 ( v4) => {
72
+ if v4. port ( ) != 0 {
73
+ ( v4. ip ( ) . to_string ( ) + ":" + & v4. port ( ) . to_string ( ) ) . into ( )
74
+ } else {
75
+ v4. ip ( ) . to_string ( ) . into ( )
76
+ }
77
+ } ,
78
+ SocketAddr :: V6 ( v6) => {
79
+ let base = if v6. scope_id ( ) != 0 {
80
+ "[" . to_owned ( ) + & v6. ip ( ) . to_string ( ) + "%" + & v6. scope_id ( ) . to_string ( ) + "]"
81
+ } else {
82
+ "[" . to_owned ( ) + & v6. ip ( ) . to_string ( ) + "]"
83
+ } ;
84
+ if v6. port ( ) != 0 {
85
+ ( base + ":" + & v6. port ( ) . to_string ( ) ) . into ( )
86
+ } else {
87
+ base. into ( )
88
+ }
89
+ }
90
+ } ;
91
+
92
+ Ok ( Authority {
93
+ data : x
94
+ } )
95
+ }
96
+
53
97
/// Attempt to convert a `Bytes` buffer to a `Authority`.
54
98
///
55
99
/// This will try to prevent a copy if the type passed is the type used
@@ -531,6 +575,7 @@ where
531
575
#[ cfg( test) ]
532
576
mod tests {
533
577
use super :: * ;
578
+ use std:: net:: { IpAddr , Ipv4Addr , Ipv6Addr , SocketAddrV6 } ;
534
579
535
580
#[ test]
536
581
fn parse_empty_string_is_error ( ) {
@@ -689,4 +734,36 @@ mod tests {
689
734
let err = Authority :: parse_non_empty ( b"]o[" ) . unwrap_err ( ) ;
690
735
assert_eq ! ( err. 0 , ErrorKind :: InvalidAuthority ) ;
691
736
}
737
+
738
+ #[ test]
739
+ fn allows_from_simple_ipv4 ( ) {
740
+ let localhost8080 = SocketAddr :: new ( IpAddr :: V4 ( Ipv4Addr :: new ( 127 , 0 , 0 , 1 ) ) , 8080 ) ;
741
+
742
+ let auth1: Authority = Authority :: from_sockaddr ( localhost8080) . unwrap ( ) ;
743
+ assert_eq ! ( auth1. port( ) . unwrap( ) , 8080 ) ;
744
+ assert_eq ! ( auth1. host( ) , "127.0.0.1" ) ;
745
+ }
746
+
747
+ #[ test]
748
+ fn allows_from_simple_ipv6 ( ) {
749
+ let example8080 = SocketAddr :: new ( IpAddr :: V6 ( Ipv6Addr :: new ( 0x2001 , 0x0db8 , 0 , 0 ,
750
+ 0 , 0 , 0 , 1 ) ) , 8080 ) ;
751
+
752
+ let auth1: Authority = Authority :: from_sockaddr ( example8080) . unwrap ( ) ;
753
+ assert_eq ! ( auth1. port( ) . unwrap( ) , 8080 ) ;
754
+ assert_eq ! ( auth1. host( ) , "[2001:db8::1]" ) ;
755
+ }
756
+
757
+ #[ test]
758
+ fn allows_from_complex_ipv6 ( ) {
759
+ let example8080scope1 = SocketAddrV6 :: new ( Ipv6Addr :: new ( 0x2001 , 0x0db8 , 0 , 0 ,
760
+ 0 , 0 , 0 , 1 ) ,
761
+ 8080 , /* port number */
762
+ 0 , /* flowid */
763
+ 1 /* scopeid */ ) ;
764
+
765
+ let auth1: Authority = Authority :: from_sockaddr ( std:: net:: SocketAddr :: V6 ( example8080scope1) ) . unwrap ( ) ;
766
+ assert_eq ! ( auth1. port( ) . unwrap( ) , 8080 ) ;
767
+ assert_eq ! ( auth1. host( ) , "[2001:db8::1%1]" ) ;
768
+ }
692
769
}
0 commit comments