From 6ed9057fd76b2d5d0dfdb3c663367ae861ab8093 Mon Sep 17 00:00:00 2001 From: Gusted Date: Fri, 19 Jan 2024 01:14:49 +0100 Subject: [PATCH] [GITEA] Fix API inconsistencies - Document the correct content types for Git archives. Add code that actually sets the correct application type for `.zip` and `.tar.gz`. - When an action (POST/PUT/DELETE method) was successful, an 204 status code should be returned instead of status code 200. - Add and adjust integration testing. - Resolves #2180 - Resolves #2181 (cherry picked from commit 6c8c4512b530e966557a5584efbbb757638b3429) (cherry picked from commit 3f74bcb14df99ee75a170813979beb5ce04c8027) --- routers/api/v1/admin/user.go | 2 +- routers/api/v1/repo/file.go | 14 +++++++++++++- templates/swagger/v1_json.tmpl | 4 +++- tests/integration/api_admin_test.go | 6 +++--- tests/integration/api_repo_archive_test.go | 3 +++ 5 files changed, 23 insertions(+), 6 deletions(-) diff --git a/routers/api/v1/admin/user.go b/routers/api/v1/admin/user.go index b4cc42ea5d..cfd9ff9cab 100644 --- a/routers/api/v1/admin/user.go +++ b/routers/api/v1/admin/user.go @@ -545,5 +545,5 @@ func RenameUser(ctx *context.APIContext) { } log.Trace("User name changed: %s -> %s", oldName, newName) - ctx.Status(http.StatusOK) + ctx.Status(http.StatusNoContent) } diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index 065d6bf8b2..46dce95929 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -257,7 +257,9 @@ func GetArchive(ctx *context.APIContext) { // --- // summary: Get an archive of a repository // produces: - // - application/json + // - application/octet-stream + // - application/zip + // - application/gzip // parameters: // - name: owner // in: path @@ -337,7 +339,17 @@ func download(ctx *context.APIContext, archiveName string, archiver *repo_model. } defer fr.Close() + contentType := "" + switch archiver.Type { + case git.ZIP: + contentType = "application/zip" + case git.TARGZ: + // Per RFC6713. + contentType = "application/gzip" + } + ctx.ServeContent(fr, &context.ServeHeaderOptions{ + ContentType: contentType, Filename: downloadName, LastModified: archiver.CreatedUnix.AsLocalTime(), }) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 7cebaa875f..40c323b9f1 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -3533,7 +3533,9 @@ "/repos/{owner}/{repo}/archive/{archive}": { "get": { "produces": [ - "application/json" + "application/octet-stream", + "application/zip", + "application/gzip" ], "tags": [ "repository" diff --git a/tests/integration/api_admin_test.go b/tests/integration/api_admin_test.go index ff7c2ddca3..3c80401e0f 100644 --- a/tests/integration/api_admin_test.go +++ b/tests/integration/api_admin_test.go @@ -254,14 +254,14 @@ func TestAPIRenameUser(t *testing.T) { // required "new_name": "User2", }).AddTokenAuth(token) - MakeRequest(t, req, http.StatusOK) + MakeRequest(t, req, http.StatusNoContent) urlStr = fmt.Sprintf("/api/v1/admin/users/%s/rename", "User2") req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ // required "new_name": "User2-2-2", }).AddTokenAuth(token) - MakeRequest(t, req, http.StatusOK) + MakeRequest(t, req, http.StatusNoContent) req = NewRequestWithValues(t, "POST", urlStr, map[string]string{ // required @@ -281,7 +281,7 @@ func TestAPIRenameUser(t *testing.T) { // required "new_name": "user2", }).AddTokenAuth(token) - MakeRequest(t, req, http.StatusOK) + MakeRequest(t, req, http.StatusNoContent) } func TestAPICron(t *testing.T) { diff --git a/tests/integration/api_repo_archive_test.go b/tests/integration/api_repo_archive_test.go index 57d3abfe84..c574d49450 100644 --- a/tests/integration/api_repo_archive_test.go +++ b/tests/integration/api_repo_archive_test.go @@ -32,18 +32,21 @@ func TestAPIDownloadArchive(t *testing.T) { bs, err := io.ReadAll(resp.Body) assert.NoError(t, err) assert.Len(t, bs, 320) + assert.EqualValues(t, "application/zip", resp.Header().Get("Content-Type")) link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master.tar.gz", user2.Name, repo.Name)) resp = MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusOK) bs, err = io.ReadAll(resp.Body) assert.NoError(t, err) assert.Len(t, bs, 266) + assert.EqualValues(t, "application/gzip", resp.Header().Get("Content-Type")) link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master.bundle", user2.Name, repo.Name)) resp = MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusOK) bs, err = io.ReadAll(resp.Body) assert.NoError(t, err) assert.Len(t, bs, 382) + assert.EqualValues(t, "application/octet-stream", resp.Header().Get("Content-Type")) link, _ = url.Parse(fmt.Sprintf("/api/v1/repos/%s/%s/archive/master", user2.Name, repo.Name)) MakeRequest(t, NewRequest(t, "GET", link.String()).AddTokenAuth(token), http.StatusBadRequest)