Fix container range bug (#34725) (#34732)

Backport #34725 by wxiaoguang

Fix #34724

Co-authored-by: wxiaoguang <wxiaoguang@gmail.com>
pull/34735/head
Giteabot 2025-06-16 06:48:04 +08:00 committed by GitHub
parent b39f7a37d1
commit 178fd90852
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 18 additions and 10 deletions

View File

@ -313,13 +313,12 @@ func InitiateUploadBlob(ctx *context.Context) {
setResponseHeaders(ctx.Resp, &containerHeaders{ setResponseHeaders(ctx.Resp, &containerHeaders{
Location: fmt.Sprintf("/v2/%s/%s/blobs/uploads/%s", ctx.Package.Owner.LowerName, image, upload.ID), Location: fmt.Sprintf("/v2/%s/%s/blobs/uploads/%s", ctx.Package.Owner.LowerName, image, upload.ID),
Range: "0-0",
UploadUUID: upload.ID, UploadUUID: upload.ID,
Status: http.StatusAccepted, Status: http.StatusAccepted,
}) })
} }
// https://docs.docker.com/registry/spec/api/#get-blob-upload // https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-a-blob-in-chunks
func GetUploadBlob(ctx *context.Context) { func GetUploadBlob(ctx *context.Context) {
uuid := ctx.PathParam("uuid") uuid := ctx.PathParam("uuid")
@ -333,13 +332,18 @@ func GetUploadBlob(ctx *context.Context) {
return return
} }
setResponseHeaders(ctx.Resp, &containerHeaders{ // FIXME: undefined behavior when the uploaded content is empty: https://github.com/opencontainers/distribution-spec/issues/578
Range: fmt.Sprintf("0-%d", upload.BytesReceived), respHeaders := &containerHeaders{
UploadUUID: upload.ID, UploadUUID: upload.ID,
Status: http.StatusNoContent, Status: http.StatusNoContent,
}) }
if upload.BytesReceived > 0 {
respHeaders.Range = fmt.Sprintf("0-%d", upload.BytesReceived-1)
}
setResponseHeaders(ctx.Resp, respHeaders)
} }
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#single-post
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-a-blob-in-chunks // https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-a-blob-in-chunks
func UploadBlob(ctx *context.Context) { func UploadBlob(ctx *context.Context) {
image := ctx.PathParam("image") image := ctx.PathParam("image")
@ -377,12 +381,15 @@ func UploadBlob(ctx *context.Context) {
return return
} }
setResponseHeaders(ctx.Resp, &containerHeaders{ respHeaders := &containerHeaders{
Location: fmt.Sprintf("/v2/%s/%s/blobs/uploads/%s", ctx.Package.Owner.LowerName, image, uploader.ID), Location: fmt.Sprintf("/v2/%s/%s/blobs/uploads/%s", ctx.Package.Owner.LowerName, image, uploader.ID),
Range: fmt.Sprintf("0-%d", uploader.Size()-1),
UploadUUID: uploader.ID, UploadUUID: uploader.ID,
Status: http.StatusAccepted, Status: http.StatusAccepted,
}) }
if contentRange != "" {
respHeaders.Range = fmt.Sprintf("0-%d", uploader.Size()-1)
}
setResponseHeaders(ctx.Resp, respHeaders)
} }
// https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-a-blob-in-chunks // https://github.com/opencontainers/distribution-spec/blob/main/spec.md#pushing-a-blob-in-chunks

View File

@ -311,7 +311,7 @@ func TestPackageContainer(t *testing.T) {
resp = MakeRequest(t, req, http.StatusNoContent) resp = MakeRequest(t, req, http.StatusNoContent)
assert.Equal(t, uuid, resp.Header().Get("Docker-Upload-Uuid")) assert.Equal(t, uuid, resp.Header().Get("Docker-Upload-Uuid"))
assert.Equal(t, fmt.Sprintf("0-%d", len(blobContent)), resp.Header().Get("Range")) assert.Equal(t, contentRange, resp.Header().Get("Range"))
pbu, err = packages_model.GetBlobUploadByID(db.DefaultContext, uuid) pbu, err = packages_model.GetBlobUploadByID(db.DefaultContext, uuid)
assert.NoError(t, err) assert.NoError(t, err)
@ -342,7 +342,8 @@ func TestPackageContainer(t *testing.T) {
resp = MakeRequest(t, req, http.StatusNoContent) resp = MakeRequest(t, req, http.StatusNoContent)
assert.Equal(t, uuid, resp.Header().Get("Docker-Upload-Uuid")) assert.Equal(t, uuid, resp.Header().Get("Docker-Upload-Uuid"))
assert.Equal(t, "0-0", resp.Header().Get("Range")) // FIXME: undefined behavior when the uploaded content is empty: https://github.com/opencontainers/distribution-spec/issues/578
assert.Nil(t, resp.Header().Values("Range"))
req = NewRequest(t, "DELETE", setting.AppURL+uploadURL[1:]). req = NewRequest(t, "DELETE", setting.AppURL+uploadURL[1:]).
AddTokenAuth(userToken) AddTokenAuth(userToken)