MyFSIO v0.2.4 Release #16
721
docs.md
721
docs.md
@@ -1507,16 +1507,723 @@ The suite covers bucket CRUD, presigned downloads, bucket policy enforcement, an
|
||||
## 14. API Matrix
|
||||
|
||||
```
|
||||
# Service Endpoints
|
||||
GET /myfsio/health # Health check
|
||||
|
||||
# Bucket Operations
|
||||
GET / # List buckets
|
||||
PUT /<bucket> # Create bucket
|
||||
DELETE /<bucket> # Remove bucket
|
||||
GET /<bucket> # List objects
|
||||
PUT /<bucket>/<key> # Upload object
|
||||
GET /<bucket>/<key> # Download object
|
||||
DELETE /<bucket>/<key> # Delete object
|
||||
GET /<bucket>?policy # Fetch policy
|
||||
PUT /<bucket>?policy # Upsert policy
|
||||
DELETE /<bucket>?policy # Delete policy
|
||||
GET /<bucket> # List objects (supports ?list-type=2)
|
||||
HEAD /<bucket> # Check bucket exists
|
||||
POST /<bucket> # POST object upload (HTML form)
|
||||
POST /<bucket>?delete # Bulk delete objects
|
||||
|
||||
# Bucket Configuration
|
||||
GET /<bucket>?policy # Fetch bucket policy
|
||||
PUT /<bucket>?policy # Upsert bucket policy
|
||||
DELETE /<bucket>?policy # Delete bucket policy
|
||||
GET /<bucket>?quota # Get bucket quota
|
||||
PUT /<bucket>?quota # Set bucket quota (admin only)
|
||||
GET /<bucket>?versioning # Get versioning status
|
||||
PUT /<bucket>?versioning # Enable/disable versioning
|
||||
GET /<bucket>?lifecycle # Get lifecycle rules
|
||||
PUT /<bucket>?lifecycle # Set lifecycle rules
|
||||
DELETE /<bucket>?lifecycle # Delete lifecycle rules
|
||||
GET /<bucket>?cors # Get CORS configuration
|
||||
PUT /<bucket>?cors # Set CORS configuration
|
||||
DELETE /<bucket>?cors # Delete CORS configuration
|
||||
GET /<bucket>?encryption # Get encryption configuration
|
||||
PUT /<bucket>?encryption # Set default encryption
|
||||
DELETE /<bucket>?encryption # Delete encryption configuration
|
||||
GET /<bucket>?acl # Get bucket ACL
|
||||
PUT /<bucket>?acl # Set bucket ACL
|
||||
GET /<bucket>?tagging # Get bucket tags
|
||||
PUT /<bucket>?tagging # Set bucket tags
|
||||
DELETE /<bucket>?tagging # Delete bucket tags
|
||||
GET /<bucket>?replication # Get replication configuration
|
||||
PUT /<bucket>?replication # Set replication rules
|
||||
DELETE /<bucket>?replication # Delete replication configuration
|
||||
GET /<bucket>?logging # Get access logging configuration
|
||||
PUT /<bucket>?logging # Set access logging
|
||||
GET /<bucket>?notification # Get event notifications
|
||||
PUT /<bucket>?notification # Set event notifications (webhooks)
|
||||
GET /<bucket>?object-lock # Get object lock configuration
|
||||
PUT /<bucket>?object-lock # Set object lock configuration
|
||||
GET /<bucket>?uploads # List active multipart uploads
|
||||
GET /<bucket>?versions # List object versions
|
||||
GET /<bucket>?location # Get bucket location/region
|
||||
|
||||
# Object Operations
|
||||
PUT /<bucket>/<key> # Upload object
|
||||
GET /<bucket>/<key> # Download object (supports Range header)
|
||||
DELETE /<bucket>/<key> # Delete object
|
||||
HEAD /<bucket>/<key> # Get object metadata
|
||||
POST /<bucket>/<key> # POST upload with policy
|
||||
POST /<bucket>/<key>?select # SelectObjectContent (SQL query)
|
||||
|
||||
# Object Configuration
|
||||
GET /<bucket>/<key>?tagging # Get object tags
|
||||
PUT /<bucket>/<key>?tagging # Set object tags
|
||||
DELETE /<bucket>/<key>?tagging # Delete object tags
|
||||
GET /<bucket>/<key>?acl # Get object ACL
|
||||
PUT /<bucket>/<key>?acl # Set object ACL
|
||||
PUT /<bucket>/<key>?retention # Set object retention
|
||||
GET /<bucket>/<key>?retention # Get object retention
|
||||
PUT /<bucket>/<key>?legal-hold # Set legal hold
|
||||
GET /<bucket>/<key>?legal-hold # Get legal hold status
|
||||
|
||||
# Multipart Upload
|
||||
POST /<bucket>/<key>?uploads # Initiate multipart upload
|
||||
PUT /<bucket>/<key>?uploadId=X&partNumber=N # Upload part
|
||||
PUT /<bucket>/<key>?uploadId=X&partNumber=N (with x-amz-copy-source) # UploadPartCopy
|
||||
POST /<bucket>/<key>?uploadId=X # Complete multipart upload
|
||||
DELETE /<bucket>/<key>?uploadId=X # Abort multipart upload
|
||||
GET /<bucket>/<key>?uploadId=X # List parts
|
||||
|
||||
# Copy Operations
|
||||
PUT /<bucket>/<key> (with x-amz-copy-source header) # CopyObject
|
||||
|
||||
# Admin API
|
||||
GET /admin/site # Get local site info
|
||||
PUT /admin/site # Update local site
|
||||
GET /admin/sites # List peer sites
|
||||
POST /admin/sites # Register peer site
|
||||
GET /admin/sites/<site_id> # Get peer site
|
||||
PUT /admin/sites/<site_id> # Update peer site
|
||||
DELETE /admin/sites/<site_id> # Unregister peer site
|
||||
GET /admin/sites/<site_id>/health # Check peer health
|
||||
GET /admin/topology # Get cluster topology
|
||||
|
||||
# KMS API
|
||||
GET /kms/keys # List KMS keys
|
||||
POST /kms/keys # Create KMS key
|
||||
GET /kms/keys/<key_id> # Get key details
|
||||
DELETE /kms/keys/<key_id> # Schedule key deletion
|
||||
POST /kms/keys/<key_id>/enable # Enable key
|
||||
POST /kms/keys/<key_id>/disable # Disable key
|
||||
POST /kms/keys/<key_id>/rotate # Rotate key material
|
||||
POST /kms/encrypt # Encrypt data
|
||||
POST /kms/decrypt # Decrypt data
|
||||
POST /kms/generate-data-key # Generate data key
|
||||
POST /kms/generate-random # Generate random bytes
|
||||
```
|
||||
|
||||
## 15. Health Check Endpoint
|
||||
|
||||
The API exposes a simple health check endpoint for monitoring and load balancer integration:
|
||||
|
||||
```bash
|
||||
# Check API health
|
||||
curl http://localhost:5000/myfsio/health
|
||||
|
||||
# Response
|
||||
{"status": "ok", "version": "0.1.7"}
|
||||
```
|
||||
|
||||
The response includes:
|
||||
- `status`: Always `"ok"` when the server is running
|
||||
- `version`: Current application version from `app/version.py`
|
||||
|
||||
Use this endpoint for:
|
||||
- Load balancer health checks
|
||||
- Kubernetes liveness/readiness probes
|
||||
- Monitoring system integration (Prometheus, Datadog, etc.)
|
||||
|
||||
## 16. Object Lock & Retention
|
||||
|
||||
Object Lock prevents objects from being deleted or overwritten for a specified retention period. MyFSIO supports both GOVERNANCE and COMPLIANCE modes.
|
||||
|
||||
### Retention Modes
|
||||
|
||||
| Mode | Description |
|
||||
|------|-------------|
|
||||
| **GOVERNANCE** | Objects can't be deleted by normal users, but users with `s3:BypassGovernanceRetention` permission can override |
|
||||
| **COMPLIANCE** | Objects can't be deleted or overwritten by anyone, including root, until the retention period expires |
|
||||
|
||||
### Enabling Object Lock
|
||||
|
||||
Object Lock must be enabled when creating a bucket:
|
||||
|
||||
```bash
|
||||
# Create bucket with Object Lock enabled
|
||||
curl -X PUT "http://localhost:5000/my-bucket" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-bucket-object-lock-enabled: true"
|
||||
|
||||
# Set default retention configuration
|
||||
curl -X PUT "http://localhost:5000/my-bucket?object-lock" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{
|
||||
"ObjectLockEnabled": "Enabled",
|
||||
"Rule": {
|
||||
"DefaultRetention": {
|
||||
"Mode": "GOVERNANCE",
|
||||
"Days": 30
|
||||
}
|
||||
}
|
||||
}'
|
||||
```
|
||||
|
||||
### Per-Object Retention
|
||||
|
||||
Set retention on individual objects:
|
||||
|
||||
```bash
|
||||
# Set object retention
|
||||
curl -X PUT "http://localhost:5000/my-bucket/important.pdf?retention" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{
|
||||
"Mode": "COMPLIANCE",
|
||||
"RetainUntilDate": "2025-12-31T23:59:59Z"
|
||||
}'
|
||||
|
||||
# Get object retention
|
||||
curl "http://localhost:5000/my-bucket/important.pdf?retention" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
```
|
||||
|
||||
### Legal Hold
|
||||
|
||||
Legal hold provides indefinite protection independent of retention settings:
|
||||
|
||||
```bash
|
||||
# Enable legal hold
|
||||
curl -X PUT "http://localhost:5000/my-bucket/document.pdf?legal-hold" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{"Status": "ON"}'
|
||||
|
||||
# Disable legal hold
|
||||
curl -X PUT "http://localhost:5000/my-bucket/document.pdf?legal-hold" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{"Status": "OFF"}'
|
||||
|
||||
# Check legal hold status
|
||||
curl "http://localhost:5000/my-bucket/document.pdf?legal-hold" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
```
|
||||
|
||||
## 17. Access Logging
|
||||
|
||||
Enable S3-style access logging to track all requests to your buckets.
|
||||
|
||||
### Configuration
|
||||
|
||||
```bash
|
||||
# Enable access logging
|
||||
curl -X PUT "http://localhost:5000/my-bucket?logging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{
|
||||
"LoggingEnabled": {
|
||||
"TargetBucket": "log-bucket",
|
||||
"TargetPrefix": "logs/my-bucket/"
|
||||
}
|
||||
}'
|
||||
|
||||
# Get logging configuration
|
||||
curl "http://localhost:5000/my-bucket?logging" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
|
||||
# Disable logging (empty configuration)
|
||||
curl -X PUT "http://localhost:5000/my-bucket?logging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{}'
|
||||
```
|
||||
|
||||
### Log Format
|
||||
|
||||
Access logs are written in S3-compatible format with fields including:
|
||||
- Timestamp, bucket, key
|
||||
- Operation (REST.GET.OBJECT, REST.PUT.OBJECT, etc.)
|
||||
- Request ID, requester, source IP
|
||||
- HTTP status, error code, bytes sent
|
||||
- Total time, turn-around time
|
||||
- Referrer, User-Agent
|
||||
|
||||
## 18. Bucket Notifications & Webhooks
|
||||
|
||||
Configure event notifications to trigger webhooks when objects are created or deleted.
|
||||
|
||||
### Supported Events
|
||||
|
||||
| Event Type | Description |
|
||||
|-----------|-------------|
|
||||
| `s3:ObjectCreated:*` | Any object creation (PUT, POST, COPY, multipart) |
|
||||
| `s3:ObjectCreated:Put` | Object created via PUT |
|
||||
| `s3:ObjectCreated:Post` | Object created via POST |
|
||||
| `s3:ObjectCreated:Copy` | Object created via COPY |
|
||||
| `s3:ObjectCreated:CompleteMultipartUpload` | Multipart upload completed |
|
||||
| `s3:ObjectRemoved:*` | Any object deletion |
|
||||
| `s3:ObjectRemoved:Delete` | Object deleted |
|
||||
| `s3:ObjectRemoved:DeleteMarkerCreated` | Delete marker created (versioned bucket) |
|
||||
|
||||
### Configuration
|
||||
|
||||
```bash
|
||||
# Set notification configuration
|
||||
curl -X PUT "http://localhost:5000/my-bucket?notification" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{
|
||||
"TopicConfigurations": [
|
||||
{
|
||||
"Id": "upload-notify",
|
||||
"TopicArn": "https://webhook.example.com/s3-events",
|
||||
"Events": ["s3:ObjectCreated:*"],
|
||||
"Filter": {
|
||||
"Key": {
|
||||
"FilterRules": [
|
||||
{"Name": "prefix", "Value": "uploads/"},
|
||||
{"Name": "suffix", "Value": ".jpg"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}'
|
||||
|
||||
# Get notification configuration
|
||||
curl "http://localhost:5000/my-bucket?notification" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
```
|
||||
|
||||
### Webhook Payload
|
||||
|
||||
The webhook receives a JSON payload similar to AWS S3 event notifications:
|
||||
|
||||
```json
|
||||
{
|
||||
"Records": [
|
||||
{
|
||||
"eventVersion": "2.1",
|
||||
"eventSource": "myfsio:s3",
|
||||
"eventTime": "2024-01-15T10:30:00.000Z",
|
||||
"eventName": "ObjectCreated:Put",
|
||||
"s3": {
|
||||
"bucket": {"name": "my-bucket"},
|
||||
"object": {
|
||||
"key": "uploads/photo.jpg",
|
||||
"size": 102400,
|
||||
"eTag": "abc123..."
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### Security Notes
|
||||
|
||||
- Webhook URLs are validated to prevent SSRF attacks
|
||||
- Internal/private IP ranges are blocked by default
|
||||
- Use HTTPS endpoints in production
|
||||
|
||||
## 19. SelectObjectContent (SQL Queries)
|
||||
|
||||
Query CSV, JSON, or Parquet files directly using SQL without downloading the entire object. Requires DuckDB to be installed.
|
||||
|
||||
### Prerequisites
|
||||
|
||||
```bash
|
||||
pip install duckdb
|
||||
```
|
||||
|
||||
### Usage
|
||||
|
||||
```bash
|
||||
# Query a CSV file
|
||||
curl -X POST "http://localhost:5000/my-bucket/data.csv?select" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{
|
||||
"Expression": "SELECT name, age FROM s3object WHERE age > 25",
|
||||
"ExpressionType": "SQL",
|
||||
"InputSerialization": {
|
||||
"CSV": {
|
||||
"FileHeaderInfo": "USE",
|
||||
"FieldDelimiter": ","
|
||||
}
|
||||
},
|
||||
"OutputSerialization": {
|
||||
"JSON": {}
|
||||
}
|
||||
}'
|
||||
|
||||
# Query a JSON file
|
||||
curl -X POST "http://localhost:5000/my-bucket/data.json?select" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{
|
||||
"Expression": "SELECT * FROM s3object s WHERE s.status = '\"active'\"",
|
||||
"ExpressionType": "SQL",
|
||||
"InputSerialization": {"JSON": {"Type": "LINES"}},
|
||||
"OutputSerialization": {"JSON": {}}
|
||||
}'
|
||||
```
|
||||
|
||||
### Supported Input Formats
|
||||
|
||||
| Format | Options |
|
||||
|--------|---------|
|
||||
| **CSV** | `FileHeaderInfo` (USE, IGNORE, NONE), `FieldDelimiter`, `QuoteCharacter`, `RecordDelimiter` |
|
||||
| **JSON** | `Type` (DOCUMENT, LINES) |
|
||||
| **Parquet** | Automatic schema detection |
|
||||
|
||||
### Output Formats
|
||||
|
||||
- **JSON**: Returns results as JSON records
|
||||
- **CSV**: Returns results as CSV
|
||||
|
||||
## 20. PostObject (HTML Form Upload)
|
||||
|
||||
Upload objects using HTML forms with policy-based authorization. Useful for browser-based direct uploads.
|
||||
|
||||
### Form Fields
|
||||
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `key` | Yes | Object key (can include `${filename}` placeholder) |
|
||||
| `file` | Yes | The file to upload |
|
||||
| `policy` | No | Base64-encoded policy document |
|
||||
| `x-amz-signature` | No | Policy signature |
|
||||
| `x-amz-credential` | No | Credential scope |
|
||||
| `x-amz-algorithm` | No | Signing algorithm (AWS4-HMAC-SHA256) |
|
||||
| `x-amz-date` | No | Request timestamp |
|
||||
| `Content-Type` | No | MIME type of the file |
|
||||
| `x-amz-meta-*` | No | Custom metadata |
|
||||
|
||||
### Example HTML Form
|
||||
|
||||
```html
|
||||
<form action="http://localhost:5000/my-bucket" method="post" enctype="multipart/form-data">
|
||||
<input type="hidden" name="key" value="uploads/${filename}">
|
||||
<input type="hidden" name="Content-Type" value="image/jpeg">
|
||||
<input type="hidden" name="x-amz-meta-user" value="john">
|
||||
<input type="file" name="file">
|
||||
<button type="submit">Upload</button>
|
||||
</form>
|
||||
```
|
||||
|
||||
### With Policy (Signed Upload)
|
||||
|
||||
For authenticated uploads, include a policy document:
|
||||
|
||||
```bash
|
||||
# Generate policy and signature using boto3 or similar
|
||||
# Then include in form:
|
||||
# - policy: base64(policy_document)
|
||||
# - x-amz-signature: HMAC-SHA256(policy, signing_key)
|
||||
# - x-amz-credential: access_key/date/region/s3/aws4_request
|
||||
# - x-amz-algorithm: AWS4-HMAC-SHA256
|
||||
# - x-amz-date: YYYYMMDDTHHMMSSZ
|
||||
```
|
||||
|
||||
## 21. Advanced S3 Operations
|
||||
|
||||
### CopyObject
|
||||
|
||||
Copy objects within or between buckets:
|
||||
|
||||
```bash
|
||||
# Copy within same bucket
|
||||
curl -X PUT "http://localhost:5000/my-bucket/copy-of-file.txt" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-copy-source: /my-bucket/original-file.txt"
|
||||
|
||||
# Copy to different bucket
|
||||
curl -X PUT "http://localhost:5000/other-bucket/file.txt" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-copy-source: /my-bucket/original-file.txt"
|
||||
|
||||
# Copy with metadata replacement
|
||||
curl -X PUT "http://localhost:5000/my-bucket/file.txt" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-copy-source: /my-bucket/file.txt" \
|
||||
-H "x-amz-metadata-directive: REPLACE" \
|
||||
-H "x-amz-meta-newkey: newvalue"
|
||||
```
|
||||
|
||||
### UploadPartCopy
|
||||
|
||||
Copy data from an existing object into a multipart upload part:
|
||||
|
||||
```bash
|
||||
# Initiate multipart upload
|
||||
UPLOAD_ID=$(curl -X POST "http://localhost:5000/my-bucket/large-file.bin?uploads" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." | jq -r '.UploadId')
|
||||
|
||||
# Copy bytes 0-10485759 from source as part 1
|
||||
curl -X PUT "http://localhost:5000/my-bucket/large-file.bin?uploadId=$UPLOAD_ID&partNumber=1" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-copy-source: /source-bucket/source-file.bin" \
|
||||
-H "x-amz-copy-source-range: bytes=0-10485759"
|
||||
|
||||
# Copy bytes 10485760-20971519 as part 2
|
||||
curl -X PUT "http://localhost:5000/my-bucket/large-file.bin?uploadId=$UPLOAD_ID&partNumber=2" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-copy-source: /source-bucket/source-file.bin" \
|
||||
-H "x-amz-copy-source-range: bytes=10485760-20971519"
|
||||
```
|
||||
|
||||
### Range Requests
|
||||
|
||||
Download partial content using the Range header:
|
||||
|
||||
```bash
|
||||
# Get first 1000 bytes
|
||||
curl "http://localhost:5000/my-bucket/large-file.bin" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "Range: bytes=0-999"
|
||||
|
||||
# Get bytes 1000-1999
|
||||
curl "http://localhost:5000/my-bucket/large-file.bin" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "Range: bytes=1000-1999"
|
||||
|
||||
# Get last 500 bytes
|
||||
curl "http://localhost:5000/my-bucket/large-file.bin" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "Range: bytes=-500"
|
||||
|
||||
# Get from byte 5000 to end
|
||||
curl "http://localhost:5000/my-bucket/large-file.bin" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "Range: bytes=5000-"
|
||||
```
|
||||
|
||||
Range responses include:
|
||||
- HTTP 206 Partial Content status
|
||||
- `Content-Range` header showing the byte range
|
||||
- `Accept-Ranges: bytes` header
|
||||
|
||||
### Conditional Requests
|
||||
|
||||
Use conditional headers for cache validation:
|
||||
|
||||
```bash
|
||||
# Only download if modified since
|
||||
curl "http://localhost:5000/my-bucket/file.txt" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "If-Modified-Since: Wed, 15 Jan 2025 10:00:00 GMT"
|
||||
|
||||
# Only download if ETag doesn't match (changed)
|
||||
curl "http://localhost:5000/my-bucket/file.txt" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "If-None-Match: \"abc123...\""
|
||||
|
||||
# Only download if ETag matches
|
||||
curl "http://localhost:5000/my-bucket/file.txt" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "If-Match: \"abc123...\""
|
||||
```
|
||||
|
||||
## 22. Access Control Lists (ACLs)
|
||||
|
||||
ACLs provide legacy-style permission management for buckets and objects.
|
||||
|
||||
### Canned ACLs
|
||||
|
||||
| ACL | Description |
|
||||
|-----|-------------|
|
||||
| `private` | Owner gets FULL_CONTROL (default) |
|
||||
| `public-read` | Owner FULL_CONTROL, public READ |
|
||||
| `public-read-write` | Owner FULL_CONTROL, public READ and WRITE |
|
||||
| `authenticated-read` | Owner FULL_CONTROL, authenticated users READ |
|
||||
|
||||
### Setting ACLs
|
||||
|
||||
```bash
|
||||
# Set bucket ACL using canned ACL
|
||||
curl -X PUT "http://localhost:5000/my-bucket?acl" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-acl: public-read"
|
||||
|
||||
# Set object ACL
|
||||
curl -X PUT "http://localhost:5000/my-bucket/file.txt?acl" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-acl: private"
|
||||
|
||||
# Set ACL during upload
|
||||
curl -X PUT "http://localhost:5000/my-bucket/file.txt" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-acl: public-read" \
|
||||
--data-binary @file.txt
|
||||
|
||||
# Get bucket ACL
|
||||
curl "http://localhost:5000/my-bucket?acl" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
|
||||
# Get object ACL
|
||||
curl "http://localhost:5000/my-bucket/file.txt?acl" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
```
|
||||
|
||||
### ACL vs Bucket Policies
|
||||
|
||||
- **ACLs**: Simple, limited options, legacy approach
|
||||
- **Bucket Policies**: Powerful, flexible, recommended for new deployments
|
||||
|
||||
For most use cases, prefer bucket policies over ACLs.
|
||||
|
||||
## 23. Object & Bucket Tagging
|
||||
|
||||
Add metadata tags to buckets and objects for organization, cost allocation, or lifecycle rule filtering.
|
||||
|
||||
### Bucket Tagging
|
||||
|
||||
```bash
|
||||
# Set bucket tags
|
||||
curl -X PUT "http://localhost:5000/my-bucket?tagging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{
|
||||
"TagSet": [
|
||||
{"Key": "Environment", "Value": "Production"},
|
||||
{"Key": "Team", "Value": "Engineering"}
|
||||
]
|
||||
}'
|
||||
|
||||
# Get bucket tags
|
||||
curl "http://localhost:5000/my-bucket?tagging" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
|
||||
# Delete bucket tags
|
||||
curl -X DELETE "http://localhost:5000/my-bucket?tagging" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
```
|
||||
|
||||
### Object Tagging
|
||||
|
||||
```bash
|
||||
# Set object tags
|
||||
curl -X PUT "http://localhost:5000/my-bucket/file.txt?tagging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{
|
||||
"TagSet": [
|
||||
{"Key": "Classification", "Value": "Confidential"},
|
||||
{"Key": "Owner", "Value": "john@example.com"}
|
||||
]
|
||||
}'
|
||||
|
||||
# Get object tags
|
||||
curl "http://localhost:5000/my-bucket/file.txt?tagging" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
|
||||
# Delete object tags
|
||||
curl -X DELETE "http://localhost:5000/my-bucket/file.txt?tagging" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
|
||||
# Set tags during upload
|
||||
curl -X PUT "http://localhost:5000/my-bucket/file.txt" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-H "x-amz-tagging: Environment=Staging&Team=QA" \
|
||||
--data-binary @file.txt
|
||||
```
|
||||
|
||||
### Tagging Limits
|
||||
|
||||
- Maximum 50 tags per object (configurable via `OBJECT_TAG_LIMIT`)
|
||||
- Tag key: 1-128 Unicode characters
|
||||
- Tag value: 0-256 Unicode characters
|
||||
|
||||
### Use Cases
|
||||
|
||||
- **Lifecycle Rules**: Filter objects for expiration by tag
|
||||
- **Access Control**: Use tag conditions in bucket policies
|
||||
- **Cost Tracking**: Group objects by project or department
|
||||
- **Automation**: Trigger actions based on object tags
|
||||
|
||||
## 24. CORS Configuration
|
||||
|
||||
Configure Cross-Origin Resource Sharing for browser-based applications.
|
||||
|
||||
### Setting CORS Rules
|
||||
|
||||
```bash
|
||||
# Set CORS configuration
|
||||
curl -X PUT "http://localhost:5000/my-bucket?cors" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..." \
|
||||
-d '{
|
||||
"CORSRules": [
|
||||
{
|
||||
"AllowedOrigins": ["https://example.com", "https://app.example.com"],
|
||||
"AllowedMethods": ["GET", "PUT", "POST", "DELETE"],
|
||||
"AllowedHeaders": ["*"],
|
||||
"ExposeHeaders": ["ETag", "x-amz-meta-*"],
|
||||
"MaxAgeSeconds": 3600
|
||||
}
|
||||
]
|
||||
}'
|
||||
|
||||
# Get CORS configuration
|
||||
curl "http://localhost:5000/my-bucket?cors" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
|
||||
# Delete CORS configuration
|
||||
curl -X DELETE "http://localhost:5000/my-bucket?cors" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
```
|
||||
|
||||
### CORS Rule Fields
|
||||
|
||||
| Field | Description |
|
||||
|-------|-------------|
|
||||
| `AllowedOrigins` | Origins allowed to access the bucket (required) |
|
||||
| `AllowedMethods` | HTTP methods allowed (GET, PUT, POST, DELETE, HEAD) |
|
||||
| `AllowedHeaders` | Request headers allowed in preflight |
|
||||
| `ExposeHeaders` | Response headers visible to browser |
|
||||
| `MaxAgeSeconds` | How long browser can cache preflight response |
|
||||
|
||||
## 25. List Objects API v2
|
||||
|
||||
MyFSIO supports both ListBucketResult v1 and v2 APIs.
|
||||
|
||||
### Using v2 API
|
||||
|
||||
```bash
|
||||
# List with v2 (supports continuation tokens)
|
||||
curl "http://localhost:5000/my-bucket?list-type=2" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
|
||||
# With prefix and delimiter (folder-like listing)
|
||||
curl "http://localhost:5000/my-bucket?list-type=2&prefix=photos/&delimiter=/" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
|
||||
# Pagination with continuation token
|
||||
curl "http://localhost:5000/my-bucket?list-type=2&max-keys=100&continuation-token=TOKEN" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
|
||||
# Start after specific key
|
||||
curl "http://localhost:5000/my-bucket?list-type=2&start-after=photos/2024/" \
|
||||
-H "X-Access-Key: ..." -H "X-Secret-Key: ..."
|
||||
```
|
||||
|
||||
### v1 vs v2 Differences
|
||||
|
||||
| Feature | v1 | v2 |
|
||||
|---------|----|----|
|
||||
| Pagination | `marker` | `continuation-token` |
|
||||
| Start position | `marker` | `start-after` |
|
||||
| Fetch owner info | Always included | Use `fetch-owner=true` |
|
||||
| Max keys | 1000 | 1000 |
|
||||
|
||||
### Query Parameters
|
||||
|
||||
| Parameter | Description |
|
||||
|-----------|-------------|
|
||||
| `list-type` | Set to `2` for v2 API |
|
||||
| `prefix` | Filter objects by key prefix |
|
||||
| `delimiter` | Group objects (typically `/`) |
|
||||
| `max-keys` | Maximum results (1-1000, default 1000) |
|
||||
| `continuation-token` | Token from previous response |
|
||||
| `start-after` | Start listing after this key |
|
||||
| `fetch-owner` | Include owner info in response |
|
||||
| `encoding-type` | Set to `url` for URL-encoded keys
|
||||
|
||||
@@ -43,6 +43,14 @@
|
||||
<li><a href="#metrics">Metrics History</a></li>
|
||||
<li><a href="#operation-metrics">Operation Metrics</a></li>
|
||||
<li><a href="#troubleshooting">Troubleshooting</a></li>
|
||||
<li><a href="#health-check">Health Check</a></li>
|
||||
<li><a href="#object-lock">Object Lock & Retention</a></li>
|
||||
<li><a href="#access-logging">Access Logging</a></li>
|
||||
<li><a href="#notifications">Notifications & Webhooks</a></li>
|
||||
<li><a href="#select-content">SelectObjectContent</a></li>
|
||||
<li><a href="#advanced-ops">Advanced Operations</a></li>
|
||||
<li><a href="#acls">Access Control Lists</a></li>
|
||||
<li><a href="#tagging">Object & Bucket Tagging</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1694,6 +1702,403 @@ curl "{{ api_base | replace('/api', '/ui') }}/metrics/operations/history?hours=6
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="health-check" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">17</span>
|
||||
<h2 class="h4 mb-0">Health Check Endpoint</h2>
|
||||
</div>
|
||||
<p class="text-muted">The API exposes a health check endpoint for monitoring and load balancer integration.</p>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Check API health
|
||||
curl {{ api_base }}/myfsio/health
|
||||
|
||||
# Response
|
||||
{"status": "ok", "version": "0.1.7"}</code></pre>
|
||||
|
||||
<p class="small text-muted mb-3">Use this endpoint for:</p>
|
||||
<ul class="small text-muted mb-0">
|
||||
<li>Load balancer health checks</li>
|
||||
<li>Kubernetes liveness/readiness probes</li>
|
||||
<li>Monitoring system integration (Prometheus, Datadog, etc.)</li>
|
||||
</ul>
|
||||
</div>
|
||||
</article>
|
||||
<article id="object-lock" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">18</span>
|
||||
<h2 class="h4 mb-0">Object Lock & Retention</h2>
|
||||
</div>
|
||||
<p class="text-muted">Object Lock prevents objects from being deleted or overwritten for a specified retention period.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Retention Modes</h3>
|
||||
<div class="table-responsive mb-3">
|
||||
<table class="table table-sm table-bordered small">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Mode</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><strong>GOVERNANCE</strong></td>
|
||||
<td>Objects can't be deleted by normal users, but admins with bypass permission can override</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>COMPLIANCE</strong></td>
|
||||
<td>Objects can't be deleted or overwritten by anyone until the retention period expires</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">API Usage</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Set object retention
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>?retention" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{"Mode": "GOVERNANCE", "RetainUntilDate": "2025-12-31T23:59:59Z"}'
|
||||
|
||||
# Enable legal hold (indefinite protection)
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>?legal-hold" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{"Status": "ON"}'
|
||||
|
||||
# Get legal hold status
|
||||
curl "{{ api_base }}/<bucket>/<key>?legal-hold" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>"</code></pre>
|
||||
|
||||
<div class="alert alert-light border mb-0">
|
||||
<div class="d-flex gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-info-circle text-muted mt-1 flex-shrink-0" viewBox="0 0 16 16">
|
||||
<path d="M8 15A7 7 0 1 1 8 1a7 7 0 0 1 0 14zm0 1A8 8 0 1 0 8 0a8 8 0 0 0 0 16z"/>
|
||||
<path d="m8.93 6.588-2.29.287-.082.38.45.083c.294.07.352.176.288.469l-.738 3.468c-.194.897.105 1.319.808 1.319.545 0 1.178-.252 1.465-.598l.088-.416c-.2.176-.492.246-.686.246-.275 0-.375-.193-.304-.533L8.93 6.588zM9 4.5a1 1 0 1 1-2 0 1 1 0 0 1 2 0z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<strong>Legal Hold:</strong> Provides indefinite protection independent of retention settings. Use for litigation holds or regulatory requirements.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="access-logging" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">19</span>
|
||||
<h2 class="h4 mb-0">Access Logging</h2>
|
||||
</div>
|
||||
<p class="text-muted">Enable S3-style access logging to track all requests to your buckets for audit and analysis.</p>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Enable access logging
|
||||
curl -X PUT "{{ api_base }}/<bucket>?logging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"LoggingEnabled": {
|
||||
"TargetBucket": "log-bucket",
|
||||
"TargetPrefix": "logs/my-bucket/"
|
||||
}
|
||||
}'
|
||||
|
||||
# Get logging configuration
|
||||
curl "{{ api_base }}/<bucket>?logging" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>"</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Log Contents</h3>
|
||||
<p class="small text-muted mb-0">Logs include: timestamp, bucket, key, operation type, request ID, requester, source IP, HTTP status, error codes, bytes transferred, timing, referrer, and User-Agent.</p>
|
||||
</div>
|
||||
</article>
|
||||
<article id="notifications" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">20</span>
|
||||
<h2 class="h4 mb-0">Notifications & Webhooks</h2>
|
||||
</div>
|
||||
<p class="text-muted">Configure event notifications to trigger webhooks when objects are created or deleted.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Supported Events</h3>
|
||||
<div class="table-responsive mb-3">
|
||||
<table class="table table-sm table-bordered small">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Event Type</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>s3:ObjectCreated:*</code></td>
|
||||
<td>Any object creation (PUT, POST, COPY, multipart)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>s3:ObjectRemoved:*</code></td>
|
||||
<td>Any object deletion</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Set notification configuration
|
||||
curl -X PUT "{{ api_base }}/<bucket>?notification" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"TopicConfigurations": [{
|
||||
"Id": "upload-notify",
|
||||
"TopicArn": "https://webhook.example.com/s3-events",
|
||||
"Events": ["s3:ObjectCreated:*"],
|
||||
"Filter": {
|
||||
"Key": {
|
||||
"FilterRules": [
|
||||
{"Name": "prefix", "Value": "uploads/"},
|
||||
{"Name": "suffix", "Value": ".jpg"}
|
||||
]
|
||||
}
|
||||
}
|
||||
}]
|
||||
}'</code></pre>
|
||||
|
||||
<div class="alert alert-warning border-warning bg-warning-subtle mb-0">
|
||||
<div class="d-flex gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="currentColor" class="bi bi-exclamation-triangle mt-1" viewBox="0 0 16 16">
|
||||
<path d="M7.938 2.016A.13.13 0 0 1 8.002 2a.13.13 0 0 1 .063.016.146.146 0 0 1 .054.057l6.857 11.667c.036.06.035.124.002.183a.163.163 0 0 1-.054.06.116.116 0 0 1-.066.017H1.146a.115.115 0 0 1-.066-.017.163.163 0 0 1-.054-.06.176.176 0 0 1 .002-.183L7.884 2.073a.147.147 0 0 1 .054-.057zm1.044-.45a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566z"/>
|
||||
<path d="M7.002 12a1 1 0 1 1 2 0 1 1 0 0 1-2 0zM7.1 5.995a.905.905 0 1 1 1.8 0l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995z"/>
|
||||
</svg>
|
||||
<div>
|
||||
<strong>Security:</strong> Webhook URLs are validated to prevent SSRF attacks. Internal/private IP ranges are blocked.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="select-content" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">21</span>
|
||||
<h2 class="h4 mb-0">SelectObjectContent (SQL)</h2>
|
||||
</div>
|
||||
<p class="text-muted">Query CSV, JSON, or Parquet files directly using SQL without downloading the entire object.</p>
|
||||
|
||||
<div class="alert alert-info border small mb-3">
|
||||
<strong>Prerequisite:</strong> Requires DuckDB to be installed (<code>pip install duckdb</code>)
|
||||
</div>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Query a CSV file
|
||||
curl -X POST "{{ api_base }}/<bucket>/data.csv?select" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"Expression": "SELECT name, age FROM s3object WHERE age > 25",
|
||||
"ExpressionType": "SQL",
|
||||
"InputSerialization": {
|
||||
"CSV": {"FileHeaderInfo": "USE", "FieldDelimiter": ","}
|
||||
},
|
||||
"OutputSerialization": {"JSON": {}}
|
||||
}'</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Supported Formats</h3>
|
||||
<div class="row g-2 mb-0">
|
||||
<div class="col-md-4">
|
||||
<div class="bg-light rounded p-2 small text-center">
|
||||
<strong>CSV</strong><br><span class="text-muted">Headers, delimiters</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="bg-light rounded p-2 small text-center">
|
||||
<strong>JSON</strong><br><span class="text-muted">Document or lines</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<div class="bg-light rounded p-2 small text-center">
|
||||
<strong>Parquet</strong><br><span class="text-muted">Auto schema</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="advanced-ops" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">22</span>
|
||||
<h2 class="h4 mb-0">Advanced S3 Operations</h2>
|
||||
</div>
|
||||
<p class="text-muted">Copy objects, upload part copies, and use range requests for partial downloads.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">CopyObject</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Copy within same bucket
|
||||
curl -X PUT "{{ api_base }}/<bucket>/copy-of-file.txt" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-copy-source: /<bucket>/original-file.txt"
|
||||
|
||||
# Copy with metadata replacement
|
||||
curl -X PUT "{{ api_base }}/<bucket>/file.txt" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-copy-source: /<bucket>/file.txt" \
|
||||
-H "x-amz-metadata-directive: REPLACE" \
|
||||
-H "x-amz-meta-newkey: newvalue"</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">UploadPartCopy</h3>
|
||||
<p class="small text-muted">Copy data from an existing object into a multipart upload part:</p>
|
||||
<pre class="mb-3"><code class="language-bash"># Copy bytes 0-10485759 from source as part 1
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>?uploadId=X&partNumber=1" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-copy-source: /source-bucket/source-file.bin" \
|
||||
-H "x-amz-copy-source-range: bytes=0-10485759"</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Range Requests</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Get first 1000 bytes
|
||||
curl "{{ api_base }}/<bucket>/<key>" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "Range: bytes=0-999"
|
||||
|
||||
# Get last 500 bytes
|
||||
curl "{{ api_base }}/<bucket>/<key>" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "Range: bytes=-500"</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Conditional Requests</h3>
|
||||
<div class="table-responsive mb-0">
|
||||
<table class="table table-sm table-bordered small mb-0">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Header</th>
|
||||
<th>Behavior</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>If-Modified-Since</code></td>
|
||||
<td>Only download if changed after date</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>If-None-Match</code></td>
|
||||
<td>Only download if ETag differs</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>If-Match</code></td>
|
||||
<td>Only download if ETag matches</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="acls" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">23</span>
|
||||
<h2 class="h4 mb-0">Access Control Lists (ACLs)</h2>
|
||||
</div>
|
||||
<p class="text-muted">ACLs provide legacy-style permission management for buckets and objects.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Canned ACLs</h3>
|
||||
<div class="table-responsive mb-3">
|
||||
<table class="table table-sm table-bordered small">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>ACL</th>
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>private</code></td>
|
||||
<td>Owner gets FULL_CONTROL (default)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>public-read</code></td>
|
||||
<td>Owner FULL_CONTROL, public READ</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>public-read-write</code></td>
|
||||
<td>Owner FULL_CONTROL, public READ and WRITE</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>authenticated-read</code></td>
|
||||
<td>Owner FULL_CONTROL, authenticated users READ</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<pre class="mb-3"><code class="language-bash"># Set bucket ACL
|
||||
curl -X PUT "{{ api_base }}/<bucket>?acl" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-acl: public-read"
|
||||
|
||||
# Set object ACL during upload
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-acl: private" \
|
||||
--data-binary @file.txt</code></pre>
|
||||
|
||||
<div class="alert alert-light border mb-0">
|
||||
<strong>Recommendation:</strong> For most use cases, prefer bucket policies over ACLs for more flexible access control.
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
<article id="tagging" class="card shadow-sm docs-section">
|
||||
<div class="card-body">
|
||||
<div class="d-flex align-items-center gap-2 mb-3">
|
||||
<span class="docs-section-kicker">24</span>
|
||||
<h2 class="h4 mb-0">Object & Bucket Tagging</h2>
|
||||
</div>
|
||||
<p class="text-muted">Add metadata tags to buckets and objects for organization, cost allocation, or lifecycle rule filtering.</p>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Object Tagging</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Set object tags
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>?tagging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"TagSet": [
|
||||
{"Key": "Classification", "Value": "Confidential"},
|
||||
{"Key": "Owner", "Value": "john@example.com"}
|
||||
]
|
||||
}'
|
||||
|
||||
# Get object tags
|
||||
curl "{{ api_base }}/<bucket>/<key>?tagging" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>"
|
||||
|
||||
# Set tags during upload
|
||||
curl -X PUT "{{ api_base }}/<bucket>/<key>" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-H "x-amz-tagging: Environment=Staging&Team=QA" \
|
||||
--data-binary @file.txt</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Bucket Tagging</h3>
|
||||
<pre class="mb-3"><code class="language-bash"># Set bucket tags
|
||||
curl -X PUT "{{ api_base }}/<bucket>?tagging" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "X-Access-Key: <key>" -H "X-Secret-Key: <secret>" \
|
||||
-d '{
|
||||
"TagSet": [
|
||||
{"Key": "Environment", "Value": "Production"},
|
||||
{"Key": "Team", "Value": "Engineering"}
|
||||
]
|
||||
}'</code></pre>
|
||||
|
||||
<h3 class="h6 text-uppercase text-muted mt-4">Use Cases</h3>
|
||||
<div class="row g-2 mb-0">
|
||||
<div class="col-md-6">
|
||||
<ul class="small text-muted mb-0 ps-3">
|
||||
<li>Filter objects for lifecycle expiration by tag</li>
|
||||
<li>Use tag conditions in bucket policies</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<ul class="small text-muted mb-0 ps-3">
|
||||
<li>Group objects by project or department</li>
|
||||
<li>Trigger automation based on object tags</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
<div class="col-xl-4 docs-sidebar-col">
|
||||
<aside class="card shadow-sm docs-sidebar">
|
||||
@@ -1716,6 +2121,14 @@ curl "{{ api_base | replace('/api', '/ui') }}/metrics/operations/history?hours=6
|
||||
<li><a href="#metrics">Metrics History</a></li>
|
||||
<li><a href="#operation-metrics">Operation Metrics</a></li>
|
||||
<li><a href="#troubleshooting">Troubleshooting</a></li>
|
||||
<li><a href="#health-check">Health Check</a></li>
|
||||
<li><a href="#object-lock">Object Lock & Retention</a></li>
|
||||
<li><a href="#access-logging">Access Logging</a></li>
|
||||
<li><a href="#notifications">Notifications & Webhooks</a></li>
|
||||
<li><a href="#select-content">SelectObjectContent</a></li>
|
||||
<li><a href="#advanced-ops">Advanced Operations</a></li>
|
||||
<li><a href="#acls">Access Control Lists</a></li>
|
||||
<li><a href="#tagging">Object & Bucket Tagging</a></li>
|
||||
</ul>
|
||||
<div class="docs-sidebar-callouts">
|
||||
<div>
|
||||
|
||||
Reference in New Issue
Block a user