internal/cdn/cdn.go
Rama main · réplica de lectura del repositorio original.
package cdn
import (
"errors"
"sync"
)
// ErrPatchRedirectUnsupported is returned by the direct-to-storage modes: a
// bare bucket cannot add the response headers a bundle patch needs.
var ErrPatchRedirectUnsupported = errors.New("this CDN mode cannot serve bundle patches")
type CDN interface {
isCDNAvailable() bool
// ComputeRedirectionURLForAsset mirrors the v2 bucket layout:
// {keyPrefix}{appId}/{branch}/{runtimeVersion}/{updateId}/{asset}.
// Missing the appId segment produces a 404 against S3/CloudFront and
// GCS-direct (objects are not at the top level anymore).
ComputeRedirectionURLForAsset(appId, branch, runtimeVersion, updateId, asset string) (string, error)
// ComputeRedirectionURLForBlob signs {keyPrefix}{appId}/cas/{hash}.
ComputeRedirectionURLForBlob(appId, hash string) (string, error)
// ComputeRedirectionURLForPatch signs
// {keyPrefix}{appId}/bsdiff/{branch}/{targetUpdateUUID}/{sourceUpdateUUID}.
ComputeRedirectionURLForPatch(appId, branch, targetUpdateUUID, sourceUpdateUUID string) (string, error)
}
func SupportsPatchRedirect() bool {
switch GetCDN().(type) {
case *CloudfrontCDN, *GenericCDN:
return true
}
return false
}
var (
cdnInstance CDN
once sync.Once
)
func GetCDN() CDN {
once.Do(func() {
cloudfrontCDN := CloudfrontCDN{}
if (&cloudfrontCDN).isCDNAvailable() {
cdnInstance = &cloudfrontCDN
return
}
// An explicitly configured CDN base URL wins over the implicit
// direct-to-storage modes: gcs-direct is available on any GCS
// deployment with signing credentials, so it would otherwise
// always shadow a deliberate CDN_BASE_URL configuration.
genericCDN := GenericCDN{}
if (&genericCDN).isCDNAvailable() {
cdnInstance = &genericCDN
return
}
gcsCDN := GCSDirectCDN{}
if (&gcsCDN).isCDNAvailable() {
cdnInstance = &gcsCDN
return
}
s3CDN := S3DirectCDN{}
if (&s3CDN).isCDNAvailable() {
cdnInstance = &s3CDN
return
}
azureCDN := AzureBlobDirectCDN{}
if (&azureCDN).isCDNAvailable() {
cdnInstance = &azureCDN
}
})
return cdnInstance
}
func ResetCDNInstance() {
cdnInstance = nil
once = sync.Once{}
}
// ResolvedType names the CDN the server actually resolved at boot:
// "cloudfront", "gcs-direct", "s3-direct", "azure-direct", "generic", or ""
// when assets are served directly.
func ResolvedType() string {
switch GetCDN().(type) {
case *CloudfrontCDN:
return "cloudfront"
case *GCSDirectCDN:
return "gcs-direct"
case *S3DirectCDN:
return "s3-direct"
case *AzureBlobDirectCDN:
return "azure-direct"
case *GenericCDN:
return "generic"
default:
return ""
}
}