Extract cloud storage URLs from a list of URLs
(&self, urls: &[String])
| 490 | |
| 491 | /// Extract cloud storage URLs from a list of URLs |
| 492 | fn extract_cloud_urls(&self, urls: &[String]) -> Vec<String> { |
| 493 | let mut cloud_urls = HashSet::new(); |
| 494 | |
| 495 | let patterns = [ |
| 496 | // S3 |
| 497 | r"https?://[a-z0-9][a-z0-9\-\.]+\.s3\.amazonaws\.com", |
| 498 | r"https?://[a-z0-9][a-z0-9\-\.]+\.s3-[a-z0-9\-]+\.amazonaws\.com", |
| 499 | r"https?://[a-z0-9][a-z0-9\-\.]+\.s3\.[a-z0-9\-]+\.amazonaws\.com", |
| 500 | r"https?://s3\.amazonaws\.com/[a-z0-9][a-z0-9\-\.]+", |
| 501 | r"https?://s3\.[a-z0-9\-]+\.amazonaws\.com/[a-z0-9][a-z0-9\-\.]+", |
| 502 | // Azure |
| 503 | r"https?://[a-z0-9]+\.blob\.core\.windows\.net", |
| 504 | // GCP |
| 505 | r"https?://storage\.googleapis\.com/[a-z0-9][a-z0-9\-_\.]+", |
| 506 | r"https?://[a-z0-9][a-z0-9\-_\.]+\.storage\.googleapis\.com", |
| 507 | // DigitalOcean Spaces |
| 508 | r"https?://[a-z0-9][a-z0-9\-\.]+\.[a-z0-9]+\.digitaloceanspaces\.com", |
| 509 | // Backblaze B2 |
| 510 | r"https?://f[0-9]+\.backblazeb2\.com/file/[a-z0-9][a-z0-9\-_]+", |
| 511 | // Wasabi |
| 512 | r"https?://s3\.[a-z0-9\-]+\.wasabisys\.com/[a-z0-9][a-z0-9\-_]+", |
| 513 | // CloudFront (may point to S3) |
| 514 | r"https?://[a-z0-9]+\.cloudfront\.net", |
| 515 | ]; |
| 516 | |
| 517 | for url in urls { |
| 518 | for pattern in &patterns { |
| 519 | if let Ok(re) = regex::Regex::new(pattern) { |
| 520 | for cap in re.find_iter(url) { |
| 521 | cloud_urls.insert(cap.as_str().to_string()); |
| 522 | } |
| 523 | } |
| 524 | } |
| 525 | } |
| 526 | |
| 527 | // Also check for common bucket naming patterns |
| 528 | for url in urls { |
| 529 | if url.contains("s3") || url.contains("bucket") || |
| 530 | url.contains("storage") || url.contains("blob") || |
| 531 | url.contains("cdn") || url.contains("assets") { |
| 532 | cloud_urls.insert(url.clone()); |
| 533 | } |
| 534 | } |
| 535 | |
| 536 | cloud_urls.into_iter().collect() |
| 537 | } |
| 538 | |
| 539 | /// Check a single cloud URL for accessibility |
| 540 | async fn check_cloud_url(client: &Client, url: &str) -> Option<CloudAsset> { |