diff options
| author | Chris Lu <chrislusf@users.noreply.github.com> | 2025-12-13 14:33:46 -0800 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-12-13 14:33:46 -0800 |
| commit | f70cd054043bb6327b6b0f3b9e54a1f6d502d2a2 (patch) | |
| tree | 57e471700f29c40eaa37161f056b5d811d49aec5 | |
| parent | f77e6ed2d4bb228187c492b9e5c04ba09362b0a6 (diff) | |
| download | seaweedfs-f70cd054043bb6327b6b0f3b9e54a1f6d502d2a2.tar.xz seaweedfs-f70cd054043bb6327b6b0f3b9e54a1f6d502d2a2.zip | |
fix: CORS wildcard subdomain matching cache race condition (#7736)
test: add HTTPS test cases for CORS wildcard subdomain matching
This adds comprehensive test coverage for HTTPS subdomain wildcard matching
in TestMatchesOrigin:
- https exact match
- https no match
- https wildcard subdomain match
- https wildcard subdomain no match (base domain)
- https wildcard subdomain no match (different domain)
- protocol mismatch tests (http pattern vs https origin and vice versa)
The matchWildcard function was already working correctly - this just adds
test coverage for the HTTPS cases that were previously untested.
Note: The cache invalidation is already handled synchronously by
setBucketMetadata() which is called via:
- UpdateBucketCORS -> UpdateBucketMetadata -> setBucketMetadata
- ClearBucketCORS -> UpdateBucketMetadata -> setBucketMetadata
Added clarifying comments to document this call chain.
| -rw-r--r-- | weed/s3api/cors/cors_test.go | 47 | ||||
| -rw-r--r-- | weed/s3api/s3_bucket_encryption.go | 6 | ||||
| -rw-r--r-- | weed/s3api/s3api_bucket_config.go | 6 |
3 files changed, 53 insertions, 6 deletions
diff --git a/weed/s3api/cors/cors_test.go b/weed/s3api/cors/cors_test.go index 8494a284d..7b72ee482 100644 --- a/weed/s3api/cors/cors_test.go +++ b/weed/s3api/cors/cors_test.go @@ -263,6 +263,49 @@ func TestMatchesOrigin(t *testing.T) { origin: "http://other.com", want: true, }, + // HTTPS test cases + { + name: "https exact match", + allowedOrigins: []string{"https://example.com"}, + origin: "https://example.com", + want: true, + }, + { + name: "https no match", + allowedOrigins: []string{"https://example.com"}, + origin: "https://other.com", + want: false, + }, + { + name: "https wildcard subdomain match", + allowedOrigins: []string{"https://*.example.com"}, + origin: "https://api.example.com", + want: true, + }, + { + name: "https wildcard subdomain no match - base domain", + allowedOrigins: []string{"https://*.example.com"}, + origin: "https://example.com", + want: false, + }, + { + name: "https wildcard subdomain no match - different domain", + allowedOrigins: []string{"https://*.example.com"}, + origin: "https://api.other.com", + want: false, + }, + { + name: "protocol mismatch - http pattern https origin", + allowedOrigins: []string{"http://*.example.com"}, + origin: "https://api.example.com", + want: false, + }, + { + name: "protocol mismatch - https pattern http origin", + allowedOrigins: []string{"https://*.example.com"}, + origin: "http://api.example.com", + want: false, + }, } for _, tt := range tests { @@ -480,7 +523,7 @@ func TestApplyHeaders(t *testing.T) { "Access-Control-Allow-Headers": "Content-Type", "Access-Control-Expose-Headers": "ETag", "Access-Control-Max-Age": "3600", - "Vary": "Origin", + "Vary": "Origin", }, }, { @@ -494,7 +537,7 @@ func TestApplyHeaders(t *testing.T) { "Access-Control-Allow-Origin": "http://example.com", "Access-Control-Allow-Methods": "GET", "Access-Control-Allow-Credentials": "true", - "Vary": "Origin", + "Vary": "Origin", }, }, } diff --git a/weed/s3api/s3_bucket_encryption.go b/weed/s3api/s3_bucket_encryption.go index 0d54c2cd5..cc9a0220f 100644 --- a/weed/s3api/s3_bucket_encryption.go +++ b/weed/s3api/s3_bucket_encryption.go @@ -218,13 +218,14 @@ func (s3a *S3ApiServer) getEncryptionConfiguration(bucket string) (*s3_pb.Encryp // updateEncryptionConfiguration updates the encryption configuration for a bucket func (s3a *S3ApiServer) updateEncryptionConfiguration(bucket string, encryptionConfig *s3_pb.EncryptionConfiguration) s3err.ErrorCode { // Update using structured API + // Note: UpdateBucketEncryption -> UpdateBucketMetadata -> setBucketMetadata + // already invalidates the cache synchronously after successful update err := s3a.UpdateBucketEncryption(bucket, encryptionConfig) if err != nil { glog.Errorf("updateEncryptionConfiguration: failed to update encryption config for bucket %s: %v", bucket, err) return s3err.ErrInternalError } - // Cache will be updated automatically via metadata subscription return s3err.ErrNone } @@ -242,13 +243,14 @@ func (s3a *S3ApiServer) removeEncryptionConfiguration(bucket string) s3err.Error } // Update using structured API + // Note: ClearBucketEncryption -> UpdateBucketMetadata -> setBucketMetadata + // already invalidates the cache synchronously after successful update err = s3a.ClearBucketEncryption(bucket) if err != nil { glog.Errorf("removeEncryptionConfiguration: failed to remove encryption config for bucket %s: %v", bucket, err) return s3err.ErrInternalError } - // Cache will be updated automatically via metadata subscription return s3err.ErrNone } diff --git a/weed/s3api/s3api_bucket_config.go b/weed/s3api/s3api_bucket_config.go index 6076f0108..94fd493a8 100644 --- a/weed/s3api/s3api_bucket_config.go +++ b/weed/s3api/s3api_bucket_config.go @@ -612,26 +612,28 @@ func (s3a *S3ApiServer) getCORSConfiguration(bucket string) (*cors.CORSConfigura // updateCORSConfiguration updates the CORS configuration for a bucket func (s3a *S3ApiServer) updateCORSConfiguration(bucket string, corsConfig *cors.CORSConfiguration) s3err.ErrorCode { // Update using structured API + // Note: UpdateBucketCORS -> UpdateBucketMetadata -> setBucketMetadata + // already invalidates the cache synchronously after successful update err := s3a.UpdateBucketCORS(bucket, corsConfig) if err != nil { glog.Errorf("updateCORSConfiguration: failed to update CORS config for bucket %s: %v", bucket, err) return s3err.ErrInternalError } - // Cache will be updated automatically via metadata subscription return s3err.ErrNone } // removeCORSConfiguration removes the CORS configuration for a bucket func (s3a *S3ApiServer) removeCORSConfiguration(bucket string) s3err.ErrorCode { // Update using structured API + // Note: ClearBucketCORS -> UpdateBucketMetadata -> setBucketMetadata + // already invalidates the cache synchronously after successful update err := s3a.ClearBucketCORS(bucket) if err != nil { glog.Errorf("removeCORSConfiguration: failed to remove CORS config for bucket %s: %v", bucket, err) return s3err.ErrInternalError } - // Cache will be updated automatically via metadata subscription return s3err.ErrNone } |
