From c134aef340376f9a51fe1cf07f185ad407dc0dd4 Mon Sep 17 00:00:00 2001 From: Kyle Evans Date: Tue, 5 May 2020 18:56:13 -0500 Subject: [PATCH] repo: Download: restore some semblance of previous behavior When archival was made async, the GET endpoint was only useful if a previous POST had initiated the download. This commit restores the previous behavior, to an extent; we'll now submit the archive request there and return a "202 Accepted" to indicate that it's processing if we didn't manage to complete the request within ~2 seconds of submission. This lets a client directly GET the archive, and gives them some indication that they may attempt to GET it again at a later time. --- routers/repo/repo.go | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 78ea55ad35..95d4701be9 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -9,6 +9,7 @@ import ( "fmt" "net/url" "strings" + "time" "code.gitea.io/gitea/models" "code.gitea.io/gitea/modules/auth" @@ -478,10 +479,24 @@ func Download(ctx *context.Context) { uri := ctx.Params("*") aReq := archiver_service.DeriveRequestFrom(ctx, uri) + downloadName := ctx.Repo.Repository.Name + "-" + aReq.GetArchiveName() if aReq.IsComplete() { - ctx.ServeFile(aReq.GetArchivePath(), ctx.Repo.Repository.Name+"-"+aReq.GetArchiveName()) + ctx.ServeFile(aReq.GetArchivePath(), downloadName) } else { - ctx.Error(404) + // We'll wait up to two seconds for the request to be satisfied, before we just return + // a 200 Accepted to indicate that we're processing. + archiver_service.ArchiveRepository(aReq) + timeout := time.Now().Add(2 * time.Second) + for { + if aReq.IsComplete() || time.Now().After(timeout) { + break + } + } + if aReq.IsComplete() { + ctx.ServeFile(aReq.GetArchivePath(), downloadName) + } else { + ctx.Error(202, "Request accepted, processing archive.") + } } } @@ -499,6 +514,18 @@ func InitiateDownload(ctx *context.Context) { complete := aReq.IsComplete() if !complete { archiver_service.ArchiveRepository(aReq) + // As with the standard Download, we'll wait up to two seconds for the request + // to be completed. The difference is that we'll never download the file from a POST + // request, only indicate the current status. If we did manage to complete the request + // in this timeframe, the download will proceed with no further overhead. + timeout := time.Now().Add(2 * time.Second) + for { + if aReq.IsComplete() || time.Now().After(timeout) { + break + } + } + + complete = aReq.IsComplete() } ctx.JSON(200, map[string]interface{}{