Table of Contents
- S3 Cross-Origin Resource Sharing (CORS)
- Overview
- Quick Start: Global CORS Configuration
- Advanced: Bucket-Level CORS Configuration
- Managing CORS Configuration
- CORS Rule Examples
- Example 1: Allow Specific Domain
- Example 2: Allow Multiple Domains
- Example 3: Wildcard Domain Support
- Example 4: Multiple Rules
- Web Application Integration
- CORS Rule Evaluation
- Performance and Caching
- Security Considerations
- Troubleshooting
- Limitations
- Best Practices
S3 Cross-Origin Resource Sharing (CORS)
SeaweedFS supports S3-compatible Cross-Origin Resource Sharing (CORS) configuration, allowing web applications to make cross-origin requests to your S3 buckets. CORS is essential for web applications that need to access resources from different domains.
Overview
CORS defines a way for web applications running at one domain to access resources at another domain. When a web application tries to access your S3 bucket from a different domain, the browser will first send a preflight OPTIONS request to check if the cross-origin request is allowed.
SeaweedFS handles CORS through:
- Global CORS configuration: Server-wide default CORS settings
- Bucket-level CORS configuration: Each bucket can have its own CORS rules
- Persistent storage: CORS configurations are stored in bucket metadata
- Automatic header handling: CORS middleware automatically applies appropriate headers
- Preflight request support: Proper handling of OPTIONS requests
Quick Start: Global CORS Configuration
The simplest way to enable CORS for all buckets is using the -s3.allowedOrigins parameter:
# Allow all origins (useful for development)
weed server -s3 -s3.allowedOrigins=*
# Allow specific origins
weed server -s3 -s3.allowedOrigins=https://app.example.com,https://admin.example.com
# Docker Compose example
services:
seaweedfs:
image: chrislusf/seaweedfs:latest
command: "server -s3 -s3.allowedOrigins=*"
This global configuration:
- Works immediately without additional setup
- Applies to all buckets by default
- Can be overridden by bucket-level CORS configuration
- Supports GET, PUT, POST, DELETE, and HEAD methods
- Allows all headers (*)
CORS Configuration Priority
SeaweedFS uses the following priority order:
- Bucket-level CORS (if configured via
aws s3api put-bucket-cors) - highest priority - Global CORS (from
-s3.allowedOriginsparameter) - fallback if no bucket config - No CORS (if neither is configured) - no CORS headers applied
This means you can set a permissive global default and override it with stricter rules for specific buckets.
Advanced: Bucket-Level CORS Configuration
Basic CORS Rule Structure
A CORS configuration consists of one or more CORS rules. Each rule defines:
<CORSConfiguration>
<CORSRule>
<ID>rule-id</ID>
<AllowedOrigin>http://example.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<AllowedMethod>POST</AllowedMethod>
<AllowedHeader>Content-Type</AllowedHeader>
<ExposeHeader>ETag</ExposeHeader>
<MaxAgeSeconds>3600</MaxAgeSeconds>
</CORSRule>
</CORSConfiguration>
CORS Rule Elements
- ID (optional): A unique identifier for the rule
- AllowedOrigin (required): Specifies which origins are allowed to access the bucket
- AllowedMethod (required): HTTP methods that are allowed (GET, PUT, POST, DELETE, HEAD)
- Note: Do NOT include
OPTIONSin AllowedMethods - it is automatically handled for preflight requests
- Note: Do NOT include
- AllowedHeader (optional): Headers that are allowed in the actual request
- ExposeHeader (optional): Headers that browsers can access from the response
- MaxAgeSeconds (optional): How long browsers can cache the preflight response
Managing CORS Configuration
Set CORS Configuration
Use the PutBucketCors API to set CORS configuration for a bucket:
aws s3api put-bucket-cors \
--bucket my-bucket \
--cors-configuration file://cors-config.json
Example cors-config.json:
{
"CORSRules": [
{
"ID": "allow-all-origins",
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET", "POST", "PUT", "DELETE", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag", "x-amz-version-id"],
"MaxAgeSeconds": 3600
}
]
}
Get CORS Configuration
Retrieve the current CORS configuration for a bucket:
aws s3api get-bucket-cors --bucket my-bucket
Response:
{
"CORSRules": [
{
"ID": "allow-all-origins",
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET", "POST", "PUT", "DELETE", "HEAD"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag", "x-amz-version-id"],
"MaxAgeSeconds": 3600
}
]
}
Delete CORS Configuration
Remove CORS configuration from a bucket:
aws s3api delete-bucket-cors --bucket my-bucket
CORS Rule Examples
Example 1: Allow Specific Domain
{
"CORSRules": [
{
"ID": "allow-example-domain",
"AllowedOrigins": ["https://example.com"],
"AllowedMethods": ["GET", "POST"],
"AllowedHeaders": ["Content-Type", "Authorization"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 1800
}
]
}
Example 2: Allow Multiple Domains
{
"CORSRules": [
{
"ID": "allow-multiple-domains",
"AllowedOrigins": [
"https://app.example.com",
"https://staging.example.com",
"https://localhost:3000"
],
"AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
"AllowedHeaders": ["*"],
"ExposeHeaders": ["ETag", "x-amz-version-id"],
"MaxAgeSeconds": 3600
}
]
}
Example 3: Wildcard Domain Support
{
"CORSRules": [
{
"ID": "allow-subdomain-wildcard",
"AllowedOrigins": ["https://*.example.com"],
"AllowedMethods": ["GET", "POST"],
"AllowedHeaders": ["Content-Type"],
"MaxAgeSeconds": 1800
}
]
}
Example 4: Multiple Rules
{
"CORSRules": [
{
"ID": "read-only-rule",
"AllowedOrigins": ["*"],
"AllowedMethods": ["GET", "HEAD"],
"AllowedHeaders": ["*"],
"MaxAgeSeconds": 3600
},
{
"ID": "write-rule",
"AllowedOrigins": ["https://admin.example.com"],
"AllowedMethods": ["PUT", "POST", "DELETE"],
"AllowedHeaders": ["Content-Type", "Authorization"],
"ExposeHeaders": ["ETag"],
"MaxAgeSeconds": 1800
}
]
}
Web Application Integration
JavaScript Example
// Configure your S3 client
const AWS = require('aws-sdk');
const s3 = new AWS.S3({
accessKeyId: 'your-access-key',
secretAccessKey: 'your-secret-key',
endpoint: 'http://localhost:8333',
s3ForcePathStyle: true,
region: 'us-east-1'
});
// Upload file from web application
const uploadFile = async (file, bucket, key) => {
const params = {
Bucket: bucket,
Key: key,
Body: file,
ContentType: file.type
};
try {
const result = await s3.upload(params).promise();
console.log('Upload successful:', result);
return result;
} catch (error) {
console.error('Upload failed:', error);
throw error;
}
};
// Download file from web application
const downloadFile = async (bucket, key) => {
const params = {
Bucket: bucket,
Key: key
};
try {
const result = await s3.getObject(params).promise();
return result.Body;
} catch (error) {
console.error('Download failed:', error);
throw error;
}
};
HTML Upload Form Example
<!DOCTYPE html>
<html>
<head>
<title>S3 Upload Example</title>
</head>
<body>
<input type="file" id="fileInput" />
<button onclick="uploadFile()">Upload</button>
<script>
async function uploadFile() {
const fileInput = document.getElementById('fileInput');
const file = fileInput.files[0];
if (!file) {
alert('Please select a file');
return;
}
const formData = new FormData();
formData.append('file', file);
try {
const response = await fetch('http://localhost:8333/my-bucket/' + file.name, {
method: 'PUT',
body: file,
headers: {
'Content-Type': file.type
}
});
if (response.ok) {
alert('Upload successful!');
} else {
alert('Upload failed: ' + response.statusText);
}
} catch (error) {
alert('Upload error: ' + error.message);
}
}
</script>
</body>
</html>
CORS Rule Evaluation
SeaweedFS evaluates CORS rules in the following order:
- Rule Matching: The first rule that matches the request origin is used
- Origin Validation: Check if the request origin matches any
AllowedOrigin - Method Validation: For preflight requests, validate the requested method
- Header Validation: For preflight requests, validate all requested headers
- Response Building: Build appropriate CORS headers based on the matched rule
Preflight Request Handling
For preflight requests (OPTIONS method), SeaweedFS:
- Checks if the origin matches an allowed origin
- Validates the requested method against allowed methods
- Validates all requested headers against allowed headers
- Returns appropriate CORS headers if all validations pass
- Returns 403 Forbidden if any validation fails
Actual Request Handling
For actual requests (GET, POST, PUT, DELETE, etc.), SeaweedFS:
- Checks if the origin matches an allowed origin
- Validates the request method against allowed methods
- Applies appropriate CORS headers to the response
- Continues with normal request processing
Performance and Caching
CORS Configuration Caching
- CORS configurations are cached in memory for 5 minutes
- Cache is automatically invalidated when configuration changes
- Multiple S3 nodes share the same cached configuration
Browser Caching
- Use
MaxAgeSecondsto control how long browsers cache preflight responses - Longer cache times reduce preflight requests but delay configuration changes
- Recommended values: 1800-3600 seconds (30-60 minutes)
Security Considerations
Origin Validation
- Never use
*forAllowedOriginin production unless absolutely necessary - Specify exact domains or use specific wildcard patterns
- Validate all origins against your application's requirements
Method Restrictions
- Only allow necessary HTTP methods
- Restrict write operations (PUT, POST, DELETE) to trusted origins
- Consider separate rules for read-only vs. write operations
Header Security
- Avoid using
*forAllowedHeadersin production - Only allow headers that your application actually needs
- Be cautious with authorization headers
Troubleshooting
Common Issues
- Invalid HTTP method: OPTIONS: Do NOT include
OPTIONSinAllowedMethods- it is automatically handled for CORS preflight requests. Only use: GET, PUT, POST, DELETE, HEAD - CORS policy error: Check that your origin is listed in
AllowedOrigins - Method not allowed: Ensure the HTTP method is in
AllowedMethods - Header blocked: Add required headers to
AllowedHeaders - Preflight failure: Verify all preflight requirements are met
Debugging Tips
- Use browser developer tools to inspect CORS headers
- Check server logs for CORS-related errors
- Test with simple requests first, then add complexity
- Verify bucket-level CORS configuration is correct
Testing CORS Configuration
# Test preflight request
curl -X OPTIONS \
-H "Origin: https://example.com" \
-H "Access-Control-Request-Method: GET" \
-H "Access-Control-Request-Headers: Content-Type" \
http://localhost:8333/my-bucket/test-object
# Test actual request
curl -X GET \
-H "Origin: https://example.com" \
http://localhost:8333/my-bucket/test-object
Limitations
- Maximum 100 CORS rules per bucket
- Wildcard support is limited to
*character - Complex regex patterns in origins are not supported
- CORS configuration is per-bucket, not per-object
Best Practices
- Specify exact origins instead of using wildcards when possible
- Use appropriate MaxAgeSeconds to balance performance and flexibility
- Implement proper error handling in your web applications
- Test CORS configuration thoroughly before deploying to production
- Monitor CORS usage and adjust rules as needed
- Keep CORS rules simple and well-documented
- Use separate rules for different access patterns (read vs. write)
Introduction
API
Configuration
- Replication
- Store file with a Time To Live
- Failover Master Server
- Erasure coding for warm storage
- Server Startup via Systemd
- Environment Variables
Filer
- Filer Setup
- Directories and Files
- File Operations Quick Reference
- Data Structure for Large Files
- Filer Data Encryption
- Filer Commands and Operations
- Filer JWT Use
Filer Stores
- Filer Cassandra Setup
- Filer Redis Setup
- Super Large Directories
- Path-Specific Filer Store
- Choosing a Filer Store
- Customize Filer Store
Management
Advanced Filer Configurations
- Migrate to Filer Store
- Add New Filer Store
- Filer Store Replication
- Filer Active Active cross cluster continuous synchronization
- Filer as a Key-Large-Value Store
- Path Specific Configuration
- Filer Change Data Capture
FUSE Mount
WebDAV
Cloud Drive
- Cloud Drive Benefits
- Cloud Drive Architecture
- Configure Remote Storage
- Mount Remote Storage
- Cache Remote Storage
- Cloud Drive Quick Setup
- Gateway to Remote Object Storage
AWS S3 API
- S3 Credentials
- Amazon S3 API
- S3 Conditional Operations
- S3 CORS
- S3 Object Lock and Retention
- S3 Object Versioning
- AWS CLI with SeaweedFS
- s3cmd with SeaweedFS
- rclone with SeaweedFS
- restic with SeaweedFS
- nodejs with Seaweed S3
- S3 API Benchmark
- S3 API FAQ
- S3 Bucket Quota
- S3 API Audit log
- S3 Nginx Proxy
- Docker Compose for S3
Server-Side Encryption
AWS IAM
Machine Learning
HDFS
- Hadoop Compatible File System
- run Spark on SeaweedFS
- run HBase on SeaweedFS
- run Presto on SeaweedFS
- Hadoop Benchmark
- HDFS via S3 connector
Replication and Backup
- Async Replication to another Filer [Deprecated]
- Async Backup
- Async Filer Metadata Backup
- Async Replication to Cloud [Deprecated]
- Kubernetes Backups and Recovery with K8up
Metadata Change Events
Messaging
- Structured Data Lake with SMQ and SQL
- Seaweed Message Queue
- SQL Queries on Message Queue
- SQL Quick Reference
- PostgreSQL-compatible Server weed db
- Pub-Sub to SMQ to SQL
- Kafka to Kafka Gateway to SMQ to SQL
Use Cases
Operations
Advanced
- Large File Handling
- Optimization
- Volume Management
- Tiered Storage
- Cloud Tier
- Cloud Monitoring
- Load Command Line Options from a file
- SRV Service Discovery
- Volume Files Structure