feat(server): improve blob sync (#15367)

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Standardized `usePresignedURL` configuration for AWS S3 and Cloudflare
R2 (including `enabled`, `urlPrefix`, and `signKey`).
- Storage upload URL generation now supports both direct provider
presigning and server-mediated proxying based on configuration.
- **Bug Fixes**
- Tightened upload and multipart validation (content type/length checks,
header vs query consistency, and stricter expiration handling).
- Improved fallback behavior when direct upload URL initialization
fails.
- **Tests**
- Updated R2 storage proxy end-to-end coverage to match the new
URL/token behavior.
- **Documentation**
  - Refreshed self-hosted JSON schema guidance for upload URL settings.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
DarkSky
2026-07-28 23:43:43 +08:00
committed by GitHub
parent b6fc0a2192
commit 00576e1e78
7 changed files with 490 additions and 347 deletions
+108 -54
View File
@@ -483,6 +483,24 @@
"type": "string"
}
}
},
"usePresignedURL": {
"type": "object",
"description": "Controls browser upload URLs. Disabled or unavailable modes fall back to server uploads.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether browser upload URLs are enabled."
},
"urlPrefix": {
"type": "string",
"description": "Optional custom origin for browser upload URLs. Provider presigned URLs also use this origin when signKey is not configured."
},
"signKey": {
"type": "string",
"description": "Optional HMAC key for signed upload URLs. Without urlPrefix, upload URLs use the server origin."
}
}
}
}
}
@@ -549,6 +567,24 @@
}
}
},
"usePresignedURL": {
"type": "object",
"description": "Controls browser upload URLs. Disabled or unavailable modes fall back to server uploads.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether browser upload URLs are enabled."
},
"urlPrefix": {
"type": "string",
"description": "Optional custom origin for browser upload URLs. Provider presigned URLs also use this origin when signKey is not configured."
},
"signKey": {
"type": "string",
"description": "Optional HMAC key for signed upload URLs. Without urlPrefix, upload URLs use the server origin."
}
}
},
"accountId": {
"type": "string",
"description": "The account id for the cloudflare r2 storage provider."
@@ -560,24 +596,6 @@
"eu"
],
"description": "Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
},
"usePresignedURL": {
"type": "object",
"description": "The presigned url config for the cloudflare r2 storage provider.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether to use presigned url for the cloudflare r2 storage provider."
},
"urlPrefix": {
"type": "string",
"description": "The custom domain URL prefix for the cloudflare r2 storage provider.\nWhen `enabled=true` and `urlPrefix` + `signKey` are provided, the server will:\n- Redirect GET requests to this custom domain with an HMAC token.\n- Return upload URLs under `/api/storage/*` for uploads.\nPresigned/upload proxy TTL is 1 hour.\nsee https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/ to configure it.\nExample value: \"https://storage.example.com\"\nExample rule: is_timed_hmac_valid_v0(\"your_secret\", http.request.uri, 10800, http.request.timestamp.sec, 6)"
},
"signKey": {
"type": "string",
"description": "The presigned key for the cloudflare r2 storage provider."
}
}
}
}
}
@@ -712,6 +730,24 @@
"type": "string"
}
}
},
"usePresignedURL": {
"type": "object",
"description": "Controls browser upload URLs. Disabled or unavailable modes fall back to server uploads.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether browser upload URLs are enabled."
},
"urlPrefix": {
"type": "string",
"description": "Optional custom origin for browser upload URLs. Provider presigned URLs also use this origin when signKey is not configured."
},
"signKey": {
"type": "string",
"description": "Optional HMAC key for signed upload URLs. Without urlPrefix, upload URLs use the server origin."
}
}
}
}
}
@@ -778,6 +814,24 @@
}
}
},
"usePresignedURL": {
"type": "object",
"description": "Controls browser upload URLs. Disabled or unavailable modes fall back to server uploads.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether browser upload URLs are enabled."
},
"urlPrefix": {
"type": "string",
"description": "Optional custom origin for browser upload URLs. Provider presigned URLs also use this origin when signKey is not configured."
},
"signKey": {
"type": "string",
"description": "Optional HMAC key for signed upload URLs. Without urlPrefix, upload URLs use the server origin."
}
}
},
"accountId": {
"type": "string",
"description": "The account id for the cloudflare r2 storage provider."
@@ -789,24 +843,6 @@
"eu"
],
"description": "Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
},
"usePresignedURL": {
"type": "object",
"description": "The presigned url config for the cloudflare r2 storage provider.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether to use presigned url for the cloudflare r2 storage provider."
},
"urlPrefix": {
"type": "string",
"description": "The custom domain URL prefix for the cloudflare r2 storage provider.\nWhen `enabled=true` and `urlPrefix` + `signKey` are provided, the server will:\n- Redirect GET requests to this custom domain with an HMAC token.\n- Return upload URLs under `/api/storage/*` for uploads.\nPresigned/upload proxy TTL is 1 hour.\nsee https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/ to configure it.\nExample value: \"https://storage.example.com\"\nExample rule: is_timed_hmac_valid_v0(\"your_secret\", http.request.uri, 10800, http.request.timestamp.sec, 6)"
},
"signKey": {
"type": "string",
"description": "The presigned key for the cloudflare r2 storage provider."
}
}
}
}
}
@@ -1391,6 +1427,24 @@
"type": "string"
}
}
},
"usePresignedURL": {
"type": "object",
"description": "Controls browser upload URLs. Disabled or unavailable modes fall back to server uploads.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether browser upload URLs are enabled."
},
"urlPrefix": {
"type": "string",
"description": "Optional custom origin for browser upload URLs. Provider presigned URLs also use this origin when signKey is not configured."
},
"signKey": {
"type": "string",
"description": "Optional HMAC key for signed upload URLs. Without urlPrefix, upload URLs use the server origin."
}
}
}
}
}
@@ -1457,6 +1511,24 @@
}
}
},
"usePresignedURL": {
"type": "object",
"description": "Controls browser upload URLs. Disabled or unavailable modes fall back to server uploads.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether browser upload URLs are enabled."
},
"urlPrefix": {
"type": "string",
"description": "Optional custom origin for browser upload URLs. Provider presigned URLs also use this origin when signKey is not configured."
},
"signKey": {
"type": "string",
"description": "Optional HMAC key for signed upload URLs. Without urlPrefix, upload URLs use the server origin."
}
}
},
"accountId": {
"type": "string",
"description": "The account id for the cloudflare r2 storage provider."
@@ -1468,24 +1540,6 @@
"eu"
],
"description": "Optional jurisdiction for the cloudflare r2 endpoint. Set to \"eu\" for EU buckets."
},
"usePresignedURL": {
"type": "object",
"description": "The presigned url config for the cloudflare r2 storage provider.",
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether to use presigned url for the cloudflare r2 storage provider."
},
"urlPrefix": {
"type": "string",
"description": "The custom domain URL prefix for the cloudflare r2 storage provider.\nWhen `enabled=true` and `urlPrefix` + `signKey` are provided, the server will:\n- Redirect GET requests to this custom domain with an HMAC token.\n- Return upload URLs under `/api/storage/*` for uploads.\nPresigned/upload proxy TTL is 1 hour.\nsee https://developers.cloudflare.com/waf/custom-rules/use-cases/configure-token-authentication/ to configure it.\nExample value: \"https://storage.example.com\"\nExample rule: is_timed_hmac_valid_v0(\"your_secret\", http.request.uri, 10800, http.request.timestamp.sec, 6)"
},
"signKey": {
"type": "string",
"description": "The presigned key for the cloudflare r2 storage provider."
}
}
}
}
}