diff --git a/docs/examples/r2.md b/docs/examples/r2.md index ecbb8150..e20d1888 100644 --- a/docs/examples/r2.md +++ b/docs/examples/r2.md @@ -22,7 +22,7 @@ It's easy to read and write data to and from Cloudflare R2 with obstore's [`S3St access_key_id = "..." secret_access_key = "..." store = S3Store.from_url( - "https://f0b62eebfbdde1133378bfe3958325f6.r2.cloudflarestorage.com/ kylebarron-public", + "https://f0b62eebfbdde1133378bfe3958325f6.r2.cloudflarestorage.com/kylebarron-public", access_key_id=access_key_id, secret_access_key=secret_access_key, ) @@ -37,7 +37,7 @@ It's easy to read and write data to and from Cloudflare R2 with obstore's [`S3St access_key_id = "..." secret_access_key = "..." bucket = "kylebarron-public" - endpoint = "https://f0b62eebfbdde1133378bfe3958325f6.r2.cloudflarestorage. com" + endpoint = "https://f0b62eebfbdde1133378bfe3958325f6.r2.cloudflarestorage.com" store = S3Store( bucket, access_key_id=access_key_id, diff --git a/pyo3-object_store/src/aws/store.rs b/pyo3-object_store/src/aws/store.rs index f8041c4a..93b6fc55 100644 --- a/pyo3-object_store/src/aws/store.rs +++ b/pyo3-object_store/src/aws/store.rs @@ -413,6 +413,16 @@ fn parse_url( config.insert_if_not_exists(AmazonS3ConfigKey::Bucket, bucket); } } + Some((account, jurisdiction, "r2", "cloudflarestorage.com")) => { + config.insert_if_not_exists(AmazonS3ConfigKey::Region, "auto"); + let endpoint = format!("https://{account}.{jurisdiction}.r2.cloudflarestorage.com"); + config.insert_if_not_exists(AmazonS3ConfigKey::Endpoint, endpoint); + + let bucket = parsed.path_segments().into_iter().flatten().next(); + if let Some(bucket) = bucket { + config.insert_if_not_exists(AmazonS3ConfigKey::Bucket, bucket); + } + } _ => { return Err(ParseUrlError::UrlNotRecognised { url: parsed.as_str().to_string(), diff --git a/tests/store/test_s3.py b/tests/store/test_s3.py index dd9061f2..4864f75c 100644 --- a/tests/store/test_s3.py +++ b/tests/store/test_s3.py @@ -75,6 +75,20 @@ async def test_from_url(): _meta = await store.head_async("2024-01-01_performance_fixed_tiles.parquet") +@pytest.mark.parametrize( + "url", + [ + "https://account.r2.cloudflarestorage.com/bucket", + "https://account.eu.r2.cloudflarestorage.com/bucket", + ], +) +def test_r2_from_url(url: str): + store = S3Store.from_url(url) + endpoint = store.config.get("endpoint") + assert endpoint is not None + assert (".eu." in endpoint) == (".eu." in url) + + def test_pickle(): store = S3Store( "ookla-open-data",