@@ -17,6 +17,7 @@ def test_allows_http_when_configured(self):
1717 with patch ("urllib.request.urlopen" ) as mock_urlopen :
1818 mock_urlopen .return_value .__enter__ = lambda s : s
1919 mock_urlopen .return_value .__exit__ = lambda s , * a : None
20+ mock_urlopen .return_value .geturl .return_value = "http://example.com/file.bin"
2021 mock_urlopen .return_value .read .return_value = b"data"
2122 with patch ("guidance._uri_validation._validate_hostname_not_private" ):
2223 bytes_from ("http://example.com/file.bin" , allow_local = True , allowed_schemes = ("http" , "https" ))
@@ -31,6 +32,7 @@ def test_allows_private_when_configured(self):
3132 with patch ("urllib.request.urlopen" ) as mock_urlopen :
3233 mock_urlopen .return_value .__enter__ = lambda s : s
3334 mock_urlopen .return_value .__exit__ = lambda s , * a : None
35+ mock_urlopen .return_value .geturl .return_value = "https://internal.example.com/file.bin"
3436 mock_urlopen .return_value .read .return_value = b"data"
3537 result = bytes_from ("https://internal.example.com/file.bin" , allow_local = True , allow_private = True )
3638 assert result == b"data"
@@ -70,6 +72,18 @@ def fake_getaddrinfo(hostname, *args, **kwargs):
7072
7173 response .read .assert_not_called ()
7274
75+ def test_rejects_non_string_redirect_target (self ):
76+ with patch ("socket.getaddrinfo" , return_value = [(None , None , None , None , ("93.184.216.34" , 443 ))]):
77+ with patch ("urllib.request.urlopen" ) as mock_urlopen :
78+ response = mock_urlopen .return_value .__enter__ .return_value
79+ response .geturl .return_value = b"https://example.com/file.bin"
80+ response .read .return_value = b"data"
81+
82+ with pytest .raises (TypeError , match = "response URL to be a string" ):
83+ bytes_from ("https://example.com/file.bin" , allow_local = True )
84+
85+ response .read .assert_not_called ()
86+
7387 def test_local_path_still_works (self , tmp_path ):
7488 test_file = tmp_path / "test.bin"
7589 test_file .write_bytes (b"local data" )
@@ -109,6 +123,7 @@ def test_timeout_passed_to_urlopen(self):
109123 with patch ("urllib.request.urlopen" ) as mock_urlopen :
110124 mock_urlopen .return_value .__enter__ = lambda s : s
111125 mock_urlopen .return_value .__exit__ = lambda s , * a : None
126+ mock_urlopen .return_value .geturl .return_value = "https://example.com/f"
112127 mock_urlopen .return_value .read .return_value = b"data"
113128 bytes_from ("https://example.com/f" , allow_local = True , timeout = 42.0 )
114129 mock_urlopen .assert_called_once_with ("https://example.com/f" , timeout = 42.0 )
0 commit comments