diff --git a/storages/utils.py b/storages/utils.py index 9235f5cd8..429250035 100644 --- a/storages/utils.py +++ b/storages/utils.py @@ -54,6 +54,11 @@ def clean_name(name): if clean_name == ".": clean_name = "" + # If name starts with a leading slash, s3 will throw an access denied error + # so we remove the leading slash + if name.startswith("/"): + clean_name = name[1:] + return clean_name diff --git a/tests/test_s3.py b/tests/test_s3.py index 0c678e395..c35882bd5 100644 --- a/tests/test_s3.py +++ b/tests/test_s3.py @@ -106,12 +106,14 @@ def test_storage_url_slashes(self): self.storage.custom_domain = "example.com" # We expect no leading slashes in the path, + # However if we encounter a leading slash we clean and remove it # and trailing slashes should be preserved. self.assertEqual(self.storage.url(""), "https://example.com/") self.assertEqual(self.storage.url("path"), "https://example.com/path") self.assertEqual(self.storage.url("path/"), "https://example.com/path/") self.assertEqual(self.storage.url("path/1"), "https://example.com/path/1") self.assertEqual(self.storage.url("path/1/"), "https://example.com/path/1/") + self.assertEqual(self.storage.url("/path/1"), "https://example.com/path/1") def test_storage_save(self): """ diff --git a/tests/test_utils.py b/tests/test_utils.py index 0895356ed..af2640a78 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -43,6 +43,11 @@ def test_clean_name_trailing_slash(self): path = utils.clean_name("path/to/somewhere/") self.assertEqual(path, "path/to/somewhere/") + def test_clean_name_leading_slash(self): + """Test the clean_name when the path has a leading slash.""" + path = utils.clean_name("/path/to/somewhere") + self.assertEqual(path, "path/to/somewhere") + def test_clean_name_windows(self): """Test the clean_name when the path has a trailing slash.""" path = utils.clean_name("path\\to\\somewhere") @@ -189,7 +194,7 @@ def test_with_string_file(self): # bytes when encoding with utf-8 vs windows-1252 vs utf-16 def test_with_string_file_specified_encoding(self): - content = "\u2122\u20AC\u2030" + content = "\u2122\u20ac\u2030" file = io.StringIO(content) file_wrapped = utils.ReadBytesWrapper(file, encoding="utf-16") @@ -197,7 +202,7 @@ def test_with_string_file_specified_encoding(self): self.assertEqual(file_wrapped.read(), content.encode("utf-16")) def test_with_string_file_detect_encoding(self): - content = "\u2122\u20AC\u2030" + content = "\u2122\u20ac\u2030" with open( file=os.path.join( os.path.dirname(__file__), "test_files", "windows-1252-encoded.txt" @@ -214,7 +219,7 @@ def test_with_string_file_detect_encoding(self): self.assertEqual(file_wrapped.read(), content.encode("windows-1252")) def test_with_string_file_fallback_encoding(self): - content = "\u2122\u20AC\u2030" + content = "\u2122\u20ac\u2030" file = io.StringIO(content) file_wrapped = utils.ReadBytesWrapper(file)