@@ -29,12 +29,18 @@ pub fn check_address(
2929 if !is_allowed {
3030 terminal:: warn!( "A component tried to make a request to non-allowed address '{address}'." ) ;
3131 let ( host, port) = ( address. host ( ) , address. port ( ) ) ;
32- eprintln ! ( "To allow requests, add 'allowed_outbound_hosts = '[\" {host}:{port}\" ]' to the manifest component section." ) ;
32+ let msg = if let Some ( port) = port {
33+ format ! ( "`allowed_outbound_hosts = [\" {host}:{port}\" ]`" )
34+ } else {
35+ format ! ( "`allowed_outbound_hosts = [\" {host}:$PORT\" ]` (where $PORT is the correct port number)" )
36+ } ;
37+ eprintln ! ( "To allow requests, add {msg} to the manifest component section." ) ;
3338 }
3439 is_allowed
3540}
3641
3742/// An address is a url-like string that contains a host, a port, and an optional scheme
43+ #[ derive( Debug ) ]
3844struct Address {
3945 inner : Url ,
4046 original : String ,
@@ -58,7 +64,7 @@ impl Address {
5864 . as_str ( )
5965 . try_into ( )
6066 . context ( "could not convert into a url" ) ;
61- has_scheme = false ;
67+ has_scheme = scheme . is_some ( ) ;
6268 match ( second_try, first_try. map_err ( |e| e. into ( ) ) ) {
6369 ( Ok ( u) , _) => Ok ( u) ,
6470 // Return an error preferring the error from the first attempt if present
@@ -86,11 +92,10 @@ impl Address {
8692 self . inner . host_str ( ) . unwrap_or_default ( )
8793 }
8894
89- fn port ( & self ) -> u16 {
95+ fn port ( & self ) -> Option < u16 > {
9096 self . inner
9197 . port_or_known_default ( )
9298 . or_else ( || well_known_port ( self . scheme ( ) ?) )
93- . unwrap_or_default ( )
9499 }
95100
96101 fn validate_as_config ( & self ) -> anyhow:: Result < ( ) > {
@@ -100,7 +105,8 @@ impl Address {
100105 if self . inner . query ( ) . is_some ( ) {
101106 anyhow:: bail!( "config '{}' contains a query string" , self ) ;
102107 }
103- if self . port ( ) == 0 {
108+ // We require configs contain a port
109+ if self . inner . port ( ) . is_none ( ) {
104110 anyhow:: bail!( "config '{}' did not contain port" , self )
105111 }
106112
@@ -171,7 +177,8 @@ impl AllowedHost {
171177 Ok ( Self {
172178 scheme : address. scheme ( ) . map ( ToOwned :: to_owned) ,
173179 host : address. host ( ) . to_owned ( ) ,
174- port : address. port ( ) ,
180+ // `unwrap` is safe as `validate_as_config` checks that it is `Some`
181+ port : address. port ( ) . unwrap ( ) ,
175182 } )
176183 }
177184
@@ -182,8 +189,9 @@ impl AllowedHost {
182189 . map ( |s| Some ( s) == address. scheme ( ) )
183190 . unwrap_or ( true ) ;
184191 let host_matches = address. host ( ) == self . host ;
185- let port_matches = address. port ( ) == self . port ;
192+ let port_matches = address. port ( ) == Some ( self . port ) ;
186193
194+ println ! ( "{scheme_matches:?} {host_matches:?} {port_matches:?}" ) ;
187195 scheme_matches && host_matches && port_matches
188196 }
189197}
@@ -203,23 +211,8 @@ mod test {
203211 use super :: * ;
204212
205213 #[ test]
206- fn test_allowed_hosts_accepts_url ( ) {
207- assert_eq ! (
208- AllowedHost :: new( Some ( "http" ) , "spin.fermyon.dev" , 80 ) ,
209- AllowedHost :: parse( "http://spin.fermyon.dev" ) . unwrap( )
210- ) ;
211- assert_eq ! (
212- AllowedHost :: new( Some ( "http" ) , "spin.fermyon.dev" , 80 ) ,
213- AllowedHost :: parse( "http://spin.fermyon.dev/" ) . unwrap( )
214- ) ;
215- assert_eq ! (
216- AllowedHost :: new( Some ( "https" ) , "spin.fermyon.dev" , 443 ) ,
217- AllowedHost :: parse( "https://spin.fermyon.dev" ) . unwrap( )
218- ) ;
219- assert_eq ! (
220- AllowedHost :: new( Some ( "postgres" ) , "spin.fermyon.dev" , 5432 ) ,
221- AllowedHost :: parse( "postgres://spin.fermyon.dev" ) . unwrap( )
222- ) ;
214+ fn test_allowed_hosts_rejects_url_without_port ( ) {
215+ assert ! ( AllowedHost :: parse( "http://spin.fermyon.dev" ) . is_err( ) ) ;
223216 }
224217
225218 #[ test]
@@ -263,10 +256,7 @@ mod test {
263256 #[ test]
264257 fn test_allowed_hosts_accepts_localhost_addresses ( ) {
265258 assert ! ( AllowedHost :: parse( "localhost" ) . is_err( ) ) ;
266- assert_eq ! (
267- AllowedHost :: new( Some ( "http" ) , "localhost" , 80 ) ,
268- AllowedHost :: parse( "http://localhost" ) . unwrap( )
269- ) ;
259+ assert ! ( AllowedHost :: parse( "http://localhost" ) . is_err( ) ) ;
270260 assert_eq ! (
271261 AllowedHost :: new( None , "localhost" , 3001 ) ,
272262 AllowedHost :: parse( "localhost:3001" ) . unwrap( )
@@ -279,10 +269,7 @@ mod test {
279269
280270 #[ test]
281271 fn test_allowed_hosts_accepts_ip_addresses ( ) {
282- assert_eq ! (
283- AllowedHost :: new( Some ( "http" ) , "192.168.1.1" , 80 ) ,
284- AllowedHost :: parse( "http://192.168.1.1" ) . unwrap( )
285- ) ;
272+ assert ! ( AllowedHost :: parse( "http://192.168.1.1" ) . is_err( ) ) ;
286273 assert_eq ! (
287274 AllowedHost :: new( Some ( "http" ) , "192.168.1.1" , 3002 ) ,
288275 AllowedHost :: parse( "http://192.168.1.1:3002" ) . unwrap( )
@@ -326,5 +313,6 @@ mod test {
326313 assert ! ( !allowed. allows( & Address :: parse( "http://example.com/" , Some ( "http" ) ) . unwrap( ) ) ) ;
327314 assert ! ( !allowed. allows( & Address :: parse( "http://google.com/" , Some ( "http" ) ) . unwrap( ) ) ) ;
328315 assert ! ( allowed. allows( & Address :: parse( "spin.fermyon.dev:443" , Some ( "https" ) ) . unwrap( ) ) ) ;
316+ assert ! ( allowed. allows( & Address :: parse( "example.com:8383" , Some ( "http" ) ) . unwrap( ) ) ) ;
329317 }
330318}
0 commit comments