Limit original size of the contents of a site manifest.

The limit is applied to the original size and not compressed size for
predictability and fairness.
This commit is contained in:
Catherine
2025-12-14 19:25:28 +00:00
parent 32ccb0920f
commit 7655400560
2 changed files with 16 additions and 4 deletions

View File

@@ -283,6 +283,7 @@ func PrepareManifest(ctx context.Context, manifest *Manifest) error {
return nil
}
var ErrSiteTooLarge = errors.New("site too large")
var ErrManifestTooLarge = errors.New("manifest too large")
// Uploads inline file data over certain size to the storage backend. Returns a copy of
@@ -325,13 +326,22 @@ func StoreManifest(
}
}
// Compute the deduplicated storage size.
var blobSizes = make(map[string]int64)
// Compute the total and deduplicated storage size.
totalSize := int64(0)
blobSizes := map[string]int64{}
for _, entry := range manifest.Contents {
totalSize += entry.GetOriginalSize()
if entry.GetType() == Type_ExternalFile {
blobSizes[string(entry.Data)] = entry.GetCompressedSize()
}
}
if uint64(totalSize) > config.Limits.MaxSiteSize.Bytes() {
return nil, fmt.Errorf("%w: contents size %s exceeds %s limit",
ErrSiteTooLarge,
datasize.ByteSize(totalSize).HR(),
config.Limits.MaxSiteSize.HR(),
)
}
for _, blobSize := range blobSizes {
*extManifest.StoredSize += blobSize
}

View File

@@ -599,8 +599,10 @@ func reportUpdateResult(w http.ResponseWriter, r *http.Request, result UpdateRes
switch result.outcome {
case UpdateError:
if errors.Is(result.err, ErrManifestTooLarge) {
w.WriteHeader(http.StatusRequestEntityTooLarge)
if errors.Is(result.err, ErrSiteTooLarge) {
w.WriteHeader(http.StatusUnprocessableEntity)
} else if errors.Is(result.err, ErrManifestTooLarge) {
w.WriteHeader(http.StatusUnprocessableEntity)
} else if errors.Is(result.err, errArchiveFormat) {
w.WriteHeader(http.StatusUnsupportedMediaType)
} else if errors.Is(result.err, ErrArchiveTooLarge) {