diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2023-05-21 09:50:53 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-21 09:50:53 +0800 |
commit | 6b33152b7dc81b38e5832a30c52cfad1902e86d0 (patch) | |
tree | 020272cc3b2d0566d286ed01f85ae74a9f48c177 /routers | |
parent | 6ba4f897231229c06ac98bf2e067665e3ef0bf23 (diff) | |
download | gitea-6b33152b7dc81b38e5832a30c52cfad1902e86d0.tar.gz gitea-6b33152b7dc81b38e5832a30c52cfad1902e86d0.zip |
Decouple the different contexts from each other (#24786)
Replace #16455
Close #21803
Mixing different Gitea contexts together causes some problems:
1. Unable to respond proper content when error occurs, eg: Web should
respond HTML while API should respond JSON
2. Unclear dependency, eg: it's unclear when Context is used in
APIContext, which fields should be initialized, which methods are
necessary.
To make things clear, this PR introduces a Base context, it only
provides basic Req/Resp/Data features.
This PR mainly moves code. There are still many legacy problems and
TODOs in code, leave unrelated changes to future PRs.
Diffstat (limited to 'routers')
27 files changed, 134 insertions, 158 deletions
diff --git a/routers/api/actions/artifacts.go b/routers/api/actions/artifacts.go index 61d432c862..4b10cd7ad1 100644 --- a/routers/api/actions/artifacts.go +++ b/routers/api/actions/artifacts.go @@ -3,7 +3,7 @@ package actions -// Github Actions Artifacts API Simple Description +// GitHub Actions Artifacts API Simple Description // // 1. Upload artifact // 1.1. Post upload url @@ -63,7 +63,6 @@ package actions import ( "compress/gzip" - gocontext "context" "crypto/md5" "encoding/base64" "errors" @@ -92,9 +91,25 @@ const ( const artifactRouteBase = "/_apis/pipelines/workflows/{run_id}/artifacts" -func ArtifactsRoutes(goctx gocontext.Context, prefix string) *web.Route { +type artifactContextKeyType struct{} + +var artifactContextKey = artifactContextKeyType{} + +type ArtifactContext struct { + *context.Base + + ActionTask *actions.ActionTask +} + +func init() { + web.RegisterHandleTypeProvider[*ArtifactContext](func(req *http.Request) web.ResponseStatusProvider { + return req.Context().Value(artifactContextKey).(*ArtifactContext) + }) +} + +func ArtifactsRoutes(prefix string) *web.Route { m := web.NewRoute() - m.Use(withContexter(goctx)) + m.Use(ArtifactContexter()) r := artifactRoutes{ prefix: prefix, @@ -115,15 +130,14 @@ func ArtifactsRoutes(goctx gocontext.Context, prefix string) *web.Route { return m } -// withContexter initializes a package context for a request. -func withContexter(goctx gocontext.Context) func(next http.Handler) http.Handler { +func ArtifactContexter() func(next http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { - ctx := context.Context{ - Resp: context.NewResponse(resp), - Data: map[string]interface{}{}, - } - defer ctx.Close() + base, baseCleanUp := context.NewBaseContext(resp, req) + defer baseCleanUp() + + ctx := &ArtifactContext{Base: base} + ctx.AppendContextValue(artifactContextKey, ctx) // action task call server api with Bearer ACTIONS_RUNTIME_TOKEN // we should verify the ACTIONS_RUNTIME_TOKEN @@ -132,6 +146,7 @@ func withContexter(goctx gocontext.Context) func(next http.Handler) http.Handler ctx.Error(http.StatusUnauthorized, "Bad authorization header") return } + authToken := strings.TrimPrefix(authHeader, "Bearer ") task, err := actions.GetRunningTaskByToken(req.Context(), authToken) if err != nil { @@ -139,16 +154,14 @@ func withContexter(goctx gocontext.Context) func(next http.Handler) http.Handler ctx.Error(http.StatusInternalServerError, "Error runner api getting task") return } - ctx.Data["task"] = task - if err := task.LoadJob(goctx); err != nil { + if err := task.LoadJob(req.Context()); err != nil { log.Error("Error runner api getting job: %v", err) ctx.Error(http.StatusInternalServerError, "Error runner api getting job") return } - ctx.Req = context.WithContext(req, &ctx) - + ctx.ActionTask = task next.ServeHTTP(ctx.Resp, ctx.Req) }) } @@ -175,13 +188,8 @@ type getUploadArtifactResponse struct { FileContainerResourceURL string `json:"fileContainerResourceUrl"` } -func (ar artifactRoutes) validateRunID(ctx *context.Context) (*actions.ActionTask, int64, bool) { - task, ok := ctx.Data["task"].(*actions.ActionTask) - if !ok { - log.Error("Error getting task in context") - ctx.Error(http.StatusInternalServerError, "Error getting task in context") - return nil, 0, false - } +func (ar artifactRoutes) validateRunID(ctx *ArtifactContext) (*actions.ActionTask, int64, bool) { + task := ctx.ActionTask runID := ctx.ParamsInt64("run_id") if task.Job.RunID != runID { log.Error("Error runID not match") @@ -192,7 +200,7 @@ func (ar artifactRoutes) validateRunID(ctx *context.Context) (*actions.ActionTas } // getUploadArtifactURL generates a URL for uploading an artifact -func (ar artifactRoutes) getUploadArtifactURL(ctx *context.Context) { +func (ar artifactRoutes) getUploadArtifactURL(ctx *ArtifactContext) { task, runID, ok := ar.validateRunID(ctx) if !ok { return @@ -220,7 +228,7 @@ func (ar artifactRoutes) getUploadArtifactURL(ctx *context.Context) { // getUploadFileSize returns the size of the file to be uploaded. // The raw size is the size of the file as reported by the header X-TFS-FileLength. -func (ar artifactRoutes) getUploadFileSize(ctx *context.Context) (int64, int64, error) { +func (ar artifactRoutes) getUploadFileSize(ctx *ArtifactContext) (int64, int64, error) { contentLength := ctx.Req.ContentLength xTfsLength, _ := strconv.ParseInt(ctx.Req.Header.Get(artifactXTfsFileLengthHeader), 10, 64) if xTfsLength > 0 { @@ -229,7 +237,7 @@ func (ar artifactRoutes) getUploadFileSize(ctx *context.Context) (int64, int64, return contentLength, contentLength, nil } -func (ar artifactRoutes) saveUploadChunk(ctx *context.Context, +func (ar artifactRoutes) saveUploadChunk(ctx *ArtifactContext, artifact *actions.ActionArtifact, contentSize, runID int64, ) (int64, error) { @@ -273,7 +281,7 @@ func (ar artifactRoutes) saveUploadChunk(ctx *context.Context, // The rules are from https://github.com/actions/toolkit/blob/main/packages/artifact/src/internal/path-and-artifact-name-validation.ts#L32 var invalidArtifactNameChars = strings.Join([]string{"\\", "/", "\"", ":", "<", ">", "|", "*", "?", "\r", "\n"}, "") -func (ar artifactRoutes) uploadArtifact(ctx *context.Context) { +func (ar artifactRoutes) uploadArtifact(ctx *ArtifactContext) { _, runID, ok := ar.validateRunID(ctx) if !ok { return @@ -341,7 +349,7 @@ func (ar artifactRoutes) uploadArtifact(ctx *context.Context) { // comfirmUploadArtifact comfirm upload artifact. // if all chunks are uploaded, merge them to one file. -func (ar artifactRoutes) comfirmUploadArtifact(ctx *context.Context) { +func (ar artifactRoutes) comfirmUploadArtifact(ctx *ArtifactContext) { _, runID, ok := ar.validateRunID(ctx) if !ok { return @@ -364,7 +372,7 @@ type chunkItem struct { Path string } -func (ar artifactRoutes) mergeArtifactChunks(ctx *context.Context, runID int64) error { +func (ar artifactRoutes) mergeArtifactChunks(ctx *ArtifactContext, runID int64) error { storageDir := fmt.Sprintf("tmp%d", runID) var chunks []*chunkItem if err := ar.fs.IterateObjects(storageDir, func(path string, obj storage.Object) error { @@ -415,14 +423,20 @@ func (ar artifactRoutes) mergeArtifactChunks(ctx *context.Context, runID int64) // use multiReader readers := make([]io.Reader, 0, len(allChunks)) - readerClosers := make([]io.Closer, 0, len(allChunks)) + closeReaders := func() { + for _, r := range readers { + _ = r.(io.Closer).Close() // it guarantees to be io.Closer by the following loop's Open function + } + readers = nil + } + defer closeReaders() + for _, c := range allChunks { - reader, err := ar.fs.Open(c.Path) - if err != nil { + var readCloser io.ReadCloser + if readCloser, err = ar.fs.Open(c.Path); err != nil { return fmt.Errorf("open chunk error: %v, %s", err, c.Path) } - readers = append(readers, reader) - readerClosers = append(readerClosers, reader) + readers = append(readers, readCloser) } mergedReader := io.MultiReader(readers...) @@ -445,11 +459,6 @@ func (ar artifactRoutes) mergeArtifactChunks(ctx *context.Context, runID int64) return fmt.Errorf("merged file size is not equal to chunk length") } - // close readers - for _, r := range readerClosers { - r.Close() - } - // save storage path to artifact log.Debug("[artifact] merge chunks to artifact: %d, %s", artifact.ID, storagePath) artifact.StoragePath = storagePath @@ -458,6 +467,8 @@ func (ar artifactRoutes) mergeArtifactChunks(ctx *context.Context, runID int64) return fmt.Errorf("update artifact error: %v", err) } + closeReaders() // close before delete + // drop chunks for _, c := range cs { if err := ar.fs.Delete(c.Path); err != nil { @@ -479,21 +490,21 @@ type ( } ) -func (ar artifactRoutes) listArtifacts(ctx *context.Context) { +func (ar artifactRoutes) listArtifacts(ctx *ArtifactContext) { _, runID, ok := ar.validateRunID(ctx) if !ok { return } - artficats, err := actions.ListArtifactsByRunID(ctx, runID) + artifacts, err := actions.ListArtifactsByRunID(ctx, runID) if err != nil { log.Error("Error getting artifacts: %v", err) ctx.Error(http.StatusInternalServerError, err.Error()) return } - artficatsData := make([]listArtifactsResponseItem, 0, len(artficats)) - for _, a := range artficats { + artficatsData := make([]listArtifactsResponseItem, 0, len(artifacts)) + for _, a := range artifacts { artficatsData = append(artficatsData, listArtifactsResponseItem{ Name: a.ArtifactName, FileContainerResourceURL: ar.buildArtifactURL(runID, a.ID, "path"), @@ -517,7 +528,7 @@ type ( } ) -func (ar artifactRoutes) getDownloadArtifactURL(ctx *context.Context) { +func (ar artifactRoutes) getDownloadArtifactURL(ctx *ArtifactContext) { _, runID, ok := ar.validateRunID(ctx) if !ok { return @@ -546,7 +557,7 @@ func (ar artifactRoutes) getDownloadArtifactURL(ctx *context.Context) { ctx.JSON(http.StatusOK, respData) } -func (ar artifactRoutes) downloadArtifact(ctx *context.Context) { +func (ar artifactRoutes) downloadArtifact(ctx *ArtifactContext) { _, runID, ok := ar.validateRunID(ctx) if !ok { return diff --git a/routers/api/packages/api.go b/routers/api/packages/api.go index aaceb8a92b..e715997e82 100644 --- a/routers/api/packages/api.go +++ b/routers/api/packages/api.go @@ -98,7 +98,7 @@ func verifyAuth(r *web.Route, authMethods []auth.Method) { func CommonRoutes(ctx gocontext.Context) *web.Route { r := web.NewRoute() - r.Use(context.PackageContexter(ctx)) + r.Use(context.PackageContexter()) verifyAuth(r, []auth.Method{ &auth.OAuth2{}, @@ -574,7 +574,7 @@ func CommonRoutes(ctx gocontext.Context) *web.Route { func ContainerRoutes(ctx gocontext.Context) *web.Route { r := web.NewRoute() - r.Use(context.PackageContexter(ctx)) + r.Use(context.PackageContexter()) verifyAuth(r, []auth.Method{ &auth.Basic{}, diff --git a/routers/api/v1/api.go b/routers/api/v1/api.go index a67a5420ac..f1e1cf946a 100644 --- a/routers/api/v1/api.go +++ b/routers/api/v1/api.go @@ -149,7 +149,7 @@ func repoAssignment() func(ctx *context.APIContext) { if err != nil { if user_model.IsErrUserNotExist(err) { if redirectUserID, err := user_model.LookupUserRedirect(userName); err == nil { - context.RedirectToUser(ctx.Context, userName, redirectUserID) + context.RedirectToUser(ctx.Base, userName, redirectUserID) } else if user_model.IsErrUserRedirectNotExist(err) { ctx.NotFound("GetUserByName", err) } else { @@ -170,7 +170,7 @@ func repoAssignment() func(ctx *context.APIContext) { if repo_model.IsErrRepoNotExist(err) { redirectRepoID, err := repo_model.LookupRedirect(owner.ID, repoName) if err == nil { - context.RedirectToRepo(ctx.Context, redirectRepoID) + context.RedirectToRepo(ctx.Base, redirectRepoID) } else if repo_model.IsErrRedirectNotExist(err) { ctx.NotFound() } else { @@ -274,7 +274,7 @@ func reqToken(requiredScope auth_model.AccessTokenScope) func(ctx *context.APICo ctx.Error(http.StatusForbidden, "reqToken", "token does not have required scope: "+requiredScope) return } - if ctx.Context.IsBasicAuth { + if ctx.IsBasicAuth { ctx.CheckForOTP() return } @@ -295,7 +295,7 @@ func reqExploreSignIn() func(ctx *context.APIContext) { func reqBasicAuth() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { - if !ctx.Context.IsBasicAuth { + if !ctx.IsBasicAuth { ctx.Error(http.StatusUnauthorized, "reqBasicAuth", "auth required") return } @@ -375,7 +375,7 @@ func reqAnyRepoReader() func(ctx *context.APIContext) { // reqOrgOwnership user should be an organization owner, or a site admin func reqOrgOwnership() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { - if ctx.Context.IsUserSiteAdmin() { + if ctx.IsUserSiteAdmin() { return } @@ -407,7 +407,7 @@ func reqOrgOwnership() func(ctx *context.APIContext) { // reqTeamMembership user should be an team member, or a site admin func reqTeamMembership() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { - if ctx.Context.IsUserSiteAdmin() { + if ctx.IsUserSiteAdmin() { return } if ctx.Org.Team == nil { @@ -444,7 +444,7 @@ func reqTeamMembership() func(ctx *context.APIContext) { // reqOrgMembership user should be an organization member, or a site admin func reqOrgMembership() func(ctx *context.APIContext) { return func(ctx *context.APIContext) { - if ctx.Context.IsUserSiteAdmin() { + if ctx.IsUserSiteAdmin() { return } @@ -512,7 +512,7 @@ func orgAssignment(args ...bool) func(ctx *context.APIContext) { if organization.IsErrOrgNotExist(err) { redirectUserID, err := user_model.LookupUserRedirect(ctx.Params(":org")) if err == nil { - context.RedirectToUser(ctx.Context, ctx.Params(":org"), redirectUserID) + context.RedirectToUser(ctx.Base, ctx.Params(":org"), redirectUserID) } else if user_model.IsErrUserRedirectNotExist(err) { ctx.NotFound("GetOrgByName", err) } else { diff --git a/routers/api/v1/misc/markup.go b/routers/api/v1/misc/markup.go index 93d5754444..7b24b353b6 100644 --- a/routers/api/v1/misc/markup.go +++ b/routers/api/v1/misc/markup.go @@ -41,7 +41,7 @@ func Markup(ctx *context.APIContext) { return } - common.RenderMarkup(ctx.Context, form.Mode, form.Text, form.Context, form.FilePath, form.Wiki) + common.RenderMarkup(ctx.Base, ctx.Repo, form.Mode, form.Text, form.Context, form.FilePath, form.Wiki) } // Markdown render markdown document to HTML @@ -76,7 +76,7 @@ func Markdown(ctx *context.APIContext) { mode = form.Mode } - common.RenderMarkup(ctx.Context, mode, form.Text, form.Context, "", form.Wiki) + common.RenderMarkup(ctx.Base, ctx.Repo, mode, form.Text, form.Context, "", form.Wiki) } // MarkdownRaw render raw markdown HTML diff --git a/routers/api/v1/misc/markup_test.go b/routers/api/v1/misc/markup_test.go index 68776613b2..fdf540fd65 100644 --- a/routers/api/v1/misc/markup_test.go +++ b/routers/api/v1/misc/markup_test.go @@ -16,7 +16,6 @@ import ( "code.gitea.io/gitea/modules/markup" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" - "code.gitea.io/gitea/modules/templates" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/modules/web" "code.gitea.io/gitea/modules/web/middleware" @@ -30,26 +29,16 @@ const ( AppSubURL = AppURL + Repo + "/" ) -func createContext(req *http.Request) (*context.Context, *httptest.ResponseRecorder) { - rnd := templates.HTMLRenderer() +func createAPIContext(req *http.Request) (*context.APIContext, *httptest.ResponseRecorder) { resp := httptest.NewRecorder() - c := &context.Context{ - Req: req, - Resp: context.NewResponse(resp), - Render: rnd, - Data: make(middleware.ContextData), - } - defer c.Close() + base, baseCleanUp := context.NewBaseContext(resp, req) + base.Data = middleware.ContextData{} + c := &context.APIContext{Base: base} + _ = baseCleanUp // during test, it doesn't need to do clean up. TODO: this can be improved later return c, resp } -func wrap(ctx *context.Context) *context.APIContext { - return &context.APIContext{ - Context: ctx, - } -} - func testRenderMarkup(t *testing.T, mode, filePath, text, responseBody string, responseCode int) { setting.AppURL = AppURL @@ -65,8 +54,7 @@ func testRenderMarkup(t *testing.T, mode, filePath, text, responseBody string, r Method: "POST", URL: requrl, } - m, resp := createContext(req) - ctx := wrap(m) + ctx, resp := createAPIContext(req) options.Text = text web.SetForm(ctx, &options) @@ -90,8 +78,7 @@ func testRenderMarkdown(t *testing.T, mode, text, responseBody string, responseC Method: "POST", URL: requrl, } - m, resp := createContext(req) - ctx := wrap(m) + ctx, resp := createAPIContext(req) options.Text = text web.SetForm(ctx, &options) @@ -211,8 +198,7 @@ func TestAPI_RenderSimple(t *testing.T) { Method: "POST", URL: requrl, } - m, resp := createContext(req) - ctx := wrap(m) + ctx, resp := createAPIContext(req) for i := 0; i < len(simpleCases); i += 2 { options.Text = simpleCases[i] @@ -231,8 +217,7 @@ func TestAPI_RenderRaw(t *testing.T) { Method: "POST", URL: requrl, } - m, resp := createContext(req) - ctx := wrap(m) + ctx, resp := createAPIContext(req) for i := 0; i < len(simpleCases); i += 2 { ctx.Req.Body = io.NopCloser(strings.NewReader(simpleCases[i])) diff --git a/routers/api/v1/notify/notifications.go b/routers/api/v1/notify/notifications.go index 3b6a9bfdc2..b22ea8a771 100644 --- a/routers/api/v1/notify/notifications.go +++ b/routers/api/v1/notify/notifications.go @@ -25,7 +25,7 @@ func NewAvailable(ctx *context.APIContext) { } func getFindNotificationOptions(ctx *context.APIContext) *activities_model.FindNotificationOptions { - before, since, err := context.GetQueryBeforeSince(ctx.Context) + before, since, err := context.GetQueryBeforeSince(ctx.Base) if err != nil { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return nil diff --git a/routers/api/v1/repo/file.go b/routers/api/v1/repo/file.go index eb63dda590..786407827c 100644 --- a/routers/api/v1/repo/file.go +++ b/routers/api/v1/repo/file.go @@ -80,7 +80,7 @@ func GetRawFile(ctx *context.APIContext) { ctx.RespHeader().Set(giteaObjectTypeHeader, string(files_service.GetObjectTypeFromTreeEntry(entry))) - if err := common.ServeBlob(ctx.Context, blob, lastModified); err != nil { + if err := common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, lastModified); err != nil { ctx.Error(http.StatusInternalServerError, "ServeBlob", err) } } @@ -137,7 +137,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) { } // OK not cached - serve! - if err := common.ServeBlob(ctx.Context, blob, lastModified); err != nil { + if err := common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, lastModified); err != nil { ctx.ServerError("ServeBlob", err) } return @@ -159,7 +159,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) { } if err := dataRc.Close(); err != nil { - log.Error("Error whilst closing blob %s reader in %-v. Error: %v", blob.ID, ctx.Context.Repo.Repository, err) + log.Error("Error whilst closing blob %s reader in %-v. Error: %v", blob.ID, ctx.Repo.Repository, err) } // Check if the blob represents a pointer @@ -173,7 +173,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) { } // OK not cached - serve! - common.ServeContentByReader(ctx.Context, ctx.Repo.TreePath, blob.Size(), bytes.NewReader(buf)) + common.ServeContentByReader(ctx.Base, ctx.Repo.TreePath, blob.Size(), bytes.NewReader(buf)) return } @@ -187,7 +187,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) { return } - common.ServeContentByReader(ctx.Context, ctx.Repo.TreePath, blob.Size(), bytes.NewReader(buf)) + common.ServeContentByReader(ctx.Base, ctx.Repo.TreePath, blob.Size(), bytes.NewReader(buf)) return } else if err != nil { ctx.ServerError("GetLFSMetaObjectByOid", err) @@ -215,7 +215,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) { } defer lfsDataRc.Close() - common.ServeContentByReadSeeker(ctx.Context, ctx.Repo.TreePath, lastModified, lfsDataRc) + common.ServeContentByReadSeeker(ctx.Base, ctx.Repo.TreePath, lastModified, lfsDataRc) } func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEntry, lastModified time.Time) { diff --git a/routers/api/v1/repo/hook_test.go b/routers/api/v1/repo/hook_test.go index 34dc990c3d..56658b45d5 100644 --- a/routers/api/v1/repo/hook_test.go +++ b/routers/api/v1/repo/hook_test.go @@ -9,7 +9,6 @@ import ( "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/models/webhook" - "code.gitea.io/gitea/modules/context" "code.gitea.io/gitea/modules/test" "github.com/stretchr/testify/assert" @@ -18,12 +17,12 @@ import ( func TestTestHook(t *testing.T) { unittest.PrepareTestEnv(t) - ctx := test.MockContext(t, "user2/repo1/wiki/_pages") + ctx := test.MockAPIContext(t, "user2/repo1/wiki/_pages") ctx.SetParams(":id", "1") test.LoadRepo(t, ctx, 1) test.LoadRepoCommit(t, ctx) test.LoadUser(t, ctx, 2) - TestHook(&context.APIContext{Context: ctx, Org: nil}) + TestHook(ctx) assert.EqualValues(t, http.StatusNoContent, ctx.Resp.Status()) unittest.AssertExistsAndLoadBean(t, &webhook.HookTask{ diff --git a/routers/api/v1/repo/issue.go b/routers/api/v1/repo/issue.go index 95528d664d..49252f7a4b 100644 --- a/routers/api/v1/repo/issue.go +++ b/routers/api/v1/repo/issue.go @@ -116,7 +116,7 @@ func SearchIssues(ctx *context.APIContext) { // "200": // "$ref": "#/responses/IssueList" - before, since, err := context.GetQueryBeforeSince(ctx.Context) + before, since, err := context.GetQueryBeforeSince(ctx.Base) if err != nil { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return @@ -368,7 +368,7 @@ func ListIssues(ctx *context.APIContext) { // responses: // "200": // "$ref": "#/responses/IssueList" - before, since, err := context.GetQueryBeforeSince(ctx.Context) + before, since, err := context.GetQueryBeforeSince(ctx.Base) if err != nil { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return diff --git a/routers/api/v1/repo/issue_comment.go b/routers/api/v1/repo/issue_comment.go index 6ae6063303..7c8f30f116 100644 --- a/routers/api/v1/repo/issue_comment.go +++ b/routers/api/v1/repo/issue_comment.go @@ -59,7 +59,7 @@ func ListIssueComments(ctx *context.APIContext) { // "200": // "$ref": "#/responses/CommentList" - before, since, err := context.GetQueryBeforeSince(ctx.Context) + before, since, err := context.GetQueryBeforeSince(ctx.Base) if err != nil { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return @@ -156,7 +156,7 @@ func ListIssueCommentsAndTimeline(ctx *context.APIContext) { // "200": // "$ref": "#/responses/TimelineList" - before, since, err := context.GetQueryBeforeSince(ctx.Context) + before, since, err := context.GetQueryBeforeSince(ctx.Base) if err != nil { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return @@ -259,7 +259,7 @@ func ListRepoIssueComments(ctx *context.APIContext) { // "200": // "$ref": "#/responses/CommentList" - before, since, err := context.GetQueryBeforeSince(ctx.Context) + before, since, err := context.GetQueryBeforeSince(ctx.Base) if err != nil { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return diff --git a/routers/api/v1/repo/issue_tracked_time.go b/routers/api/v1/repo/issue_tracked_time.go index 16bb8cb73d..1ff934950c 100644 --- a/routers/api/v1/repo/issue_tracked_time.go +++ b/routers/api/v1/repo/issue_tracked_time.go @@ -103,7 +103,7 @@ func ListTrackedTimes(ctx *context.APIContext) { opts.UserID = user.ID } - if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = context.GetQueryBeforeSince(ctx.Context); err != nil { + if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = context.GetQueryBeforeSince(ctx.Base); err != nil { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } @@ -522,7 +522,7 @@ func ListTrackedTimesByRepository(ctx *context.APIContext) { } var err error - if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = context.GetQueryBeforeSince(ctx.Context); err != nil { + if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = context.GetQueryBeforeSince(ctx.Base); err != nil { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } @@ -596,7 +596,7 @@ func ListMyTrackedTimes(ctx *context.APIContext) { } var err error - if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = context.GetQueryBeforeSince(ctx.Context); err != nil { + if opts.CreatedBeforeUnix, opts.CreatedAfterUnix, err = context.GetQueryBeforeSince(ctx.Base); err != nil { ctx.Error(http.StatusUnprocessableEntity, "GetQueryBeforeSince", err) return } diff --git a/routers/api/v1/repo/migrate.go b/routers/api/v1/repo/migrate.go index efce39e520..b458cd122b 100644 --- a/routers/api/v1/repo/migrate.go +++ b/routers/api/v1/repo/migrate.go @@ -79,7 +79,7 @@ func Migrate(ctx *context.APIContext) { return } - if ctx.HasError() { + if ctx.HasAPIError() { ctx.Error(http.StatusUnprocessableEntity, "", ctx.GetErrMsg()) return } diff --git a/routers/api/v1/repo/repo_test.go b/routers/api/v1/repo/repo_test.go index 59c3bde819..e1bdea5c82 100644 --- a/routers/api/v1/repo/repo_test.go +++ b/routers/api/v1/repo/repo_test.go @@ -9,7 +9,6 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" - "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/modules/web" @@ -20,7 +19,7 @@ import ( func TestRepoEdit(t *testing.T) { unittest.PrepareTestEnv(t) - ctx := test.MockContext(t, "user2/repo1") + ctx := test.MockAPIContext(t, "user2/repo1") test.LoadRepo(t, ctx, 1) test.LoadUser(t, ctx, 2) ctx.Repo.Owner = ctx.Doer @@ -54,9 +53,8 @@ func TestRepoEdit(t *testing.T) { Archived: &archived, } - apiCtx := &context.APIContext{Context: ctx, Org: nil} - web.SetForm(apiCtx, &opts) - Edit(apiCtx) + web.SetForm(ctx, &opts) + Edit(ctx) assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ @@ -67,7 +65,7 @@ func TestRepoEdit(t *testing.T) { func TestRepoEditNameChange(t *testing.T) { unittest.PrepareTestEnv(t) - ctx := test.MockContext(t, "user2/repo1") + ctx := test.MockAPIContext(t, "user2/repo1") test.LoadRepo(t, ctx, 1) test.LoadUser(t, ctx, 2) ctx.Repo.Owner = ctx.Doer @@ -76,9 +74,8 @@ func TestRepoEditNameChange(t *testing.T) { Name: &name, } - apiCtx := &context.APIContext{Context: ctx, Org: nil} - web.SetForm(apiCtx, &opts) - Edit(apiCtx) + web.SetForm(ctx, &opts) + Edit(ctx) assert.EqualValues(t, http.StatusOK, ctx.Resp.Status()) unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ diff --git a/routers/api/v1/repo/status.go b/routers/api/v1/repo/status.go index 5158f38e14..c1110ebce5 100644 --- a/routers/api/v1/repo/status.go +++ b/routers/api/v1/repo/status.go @@ -183,7 +183,7 @@ func getCommitStatuses(ctx *context.APIContext, sha string) { ctx.Error(http.StatusBadRequest, "ref/sha not given", nil) return } - sha = utils.MustConvertToSHA1(ctx.Context, sha) + sha = utils.MustConvertToSHA1(ctx.Base, ctx.Repo, sha) repo := ctx.Repo.Repository listOptions := utils.GetListOptions(ctx) diff --git a/routers/api/v1/user/helper.go b/routers/api/v1/user/helper.go index 28f600ad92..4b642910b1 100644 --- a/routers/api/v1/user/helper.go +++ b/routers/api/v1/user/helper.go @@ -17,7 +17,7 @@ func GetUserByParamsName(ctx *context.APIContext, name string) *user_model.User if err != nil { if user_model.IsErrUserNotExist(err) { if redirectUserID, err2 := user_model.LookupUserRedirect(username); err2 == nil { - context.RedirectToUser(ctx.Context, username, redirectUserID) + context.RedirectToUser(ctx.Base, username, redirectUserID) } else { ctx.NotFound("GetUserByName", err) } diff --git a/routers/api/v1/utils/git.go b/routers/api/v1/utils/git.go index eaf0f5fd37..32f5c85319 100644 --- a/routers/api/v1/utils/git.go +++ b/routers/api/v1/utils/git.go @@ -4,6 +4,7 @@ package utils import ( + gocontext "context" "fmt" "net/http" @@ -33,7 +34,7 @@ func ResolveRefOrSha(ctx *context.APIContext, ref string) string { } } - sha = MustConvertToSHA1(ctx.Context, sha) + sha = MustConvertToSHA1(ctx, ctx.Repo, sha) if ctx.Repo.GitRepo != nil { err := ctx.Repo.GitRepo.AddLastCommitCache(ctx.Repo.Repository.GetCommitsCountCacheKey(ref, ref != sha), ctx.Repo.Repository.FullName(), sha) @@ -69,7 +70,7 @@ func searchRefCommitByType(ctx *context.APIContext, refType, filter string) (str } // ConvertToSHA1 returns a full-length SHA1 from a potential ID string -func ConvertToSHA1(ctx *context.Context, commitID string) (git.SHA1, error) { +func ConvertToSHA1(ctx gocontext.Context, repo *context.Repository, commitID string) (git.SHA1, error) { if len(commitID) == git.SHAFullLength && git.IsValidSHAPattern(commitID) { sha1, err := git.NewIDFromString(commitID) if err == nil { @@ -77,7 +78,7 @@ func ConvertToSHA1(ctx *context.Context, commitID string) (git.SHA1, error) { } } - gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, ctx.Repo.Repository.RepoPath()) + gitRepo, closer, err := git.RepositoryFromContextOrOpen(ctx, repo.Repository.RepoPath()) if err != nil { return git.SHA1{}, fmt.Errorf("RepositoryFromContextOrOpen: %w", err) } @@ -87,8 +88,8 @@ func ConvertToSHA1(ctx *context.Context, commitID string) (git.SHA1, error) { } // MustConvertToSHA1 returns a full-length SHA1 string from a potential ID string, or returns origin input if it can't convert to SHA1 -func MustConvertToSHA1(ctx *context.Context, commitID string) string { - sha, err := ConvertToSHA1(ctx, commitID) +func MustConvertToSHA1(ctx gocontext.Context, repo *context.Repository, commitID string) string { + sha, err := ConvertToSHA1(ctx, repo, commitID) if err != nil { return commitID } diff --git a/routers/common/markup.go b/routers/common/markup.go index 3acd12721e..5f412014d7 100644 --- a/routers/common/markup.go +++ b/routers/common/markup.go @@ -19,7 +19,7 @@ import ( ) // RenderMarkup renders markup text for the /markup and /markdown endpoints -func RenderMarkup(ctx *context.Context, mode, text, urlPrefix, filePath string, wiki bool) { +func RenderMarkup(ctx *context.Base, repo *context.Repository, mode, text, urlPrefix, filePath string, wiki bool) { var markupType string relativePath := "" @@ -63,11 +63,11 @@ func RenderMarkup(ctx *context.Context, mode, text, urlPrefix, filePath string, } meta := map[string]string{} - if ctx.Repo != nil && ctx.Repo.Repository != nil { + if repo != nil && repo.Repository != nil { if mode == "comment" { - meta = ctx.Repo.Repository.ComposeMetas() + meta = repo.Repository.ComposeMetas() } else { - meta = ctx.Repo.Repository.ComposeDocumentMetas() + meta = repo.Repository.ComposeDocumentMetas() } } if mode != "comment" { diff --git a/routers/common/middleware.go b/routers/common/middleware.go index c1ee9dd765..a25ff1ee00 100644 --- a/routers/common/middleware.go +++ b/routers/common/middleware.go @@ -42,7 +42,7 @@ func ProtocolMiddlewares() (handlers []any) { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { ctx, _, finished := process.GetManager().AddTypedContext(req.Context(), fmt.Sprintf("%s: %s", req.Method, req.RequestURI), process.RequestProcessType, true) defer finished() - next.ServeHTTP(context.NewResponse(resp), req.WithContext(cache.WithCacheContext(ctx))) + next.ServeHTTP(context.WrapResponseWriter(resp), req.WithContext(cache.WithCacheContext(ctx))) }) }) diff --git a/routers/common/serve.go b/routers/common/serve.go index 59b993328e..3094ee6a6e 100644 --- a/routers/common/serve.go +++ b/routers/common/serve.go @@ -15,7 +15,7 @@ import ( ) // ServeBlob download a git.Blob -func ServeBlob(ctx *context.Context, blob *git.Blob, lastModified time.Time) error { +func ServeBlob(ctx *context.Base, filePath string, blob *git.Blob, lastModified time.Time) error { if httpcache.HandleGenericETagTimeCache(ctx.Req, ctx.Resp, `"`+blob.ID.String()+`"`, lastModified) { return nil } @@ -30,14 +30,14 @@ func ServeBlob(ctx *context.Context, blob *git.Blob, lastModified time.Time) err } }() - httplib.ServeContentByReader(ctx.Req, ctx.Resp, ctx.Repo.TreePath, blob.Size(), dataRc) + httplib.ServeContentByReader(ctx.Req, ctx.Resp, filePath, blob.Size(), dataRc) return nil } -func ServeContentByReader(ctx *context.Context, filePath string, size int64, reader io.Reader) { +func ServeContentByReader(ctx *context.Base, filePath string, size int64, reader io.Reader) { httplib.ServeContentByReader(ctx.Req, ctx.Resp, filePath, size, reader) } -func ServeContentByReadSeeker(ctx *context.Context, filePath string, modTime time.Time, reader io.ReadSeeker) { +func ServeContentByReadSeeker(ctx *context.Base, filePath string, modTime time.Time, reader io.ReadSeeker) { httplib.ServeContentByReadSeeker(ctx.Req, ctx.Resp, filePath, modTime, reader) } diff --git a/routers/init.go b/routers/init.go index 087d8c2915..5737ef3dc0 100644 --- a/routers/init.go +++ b/routers/init.go @@ -198,7 +198,7 @@ func NormalRoutes(ctx context.Context) *web.Route { // In Github, it uses ACTIONS_RUNTIME_URL=https://pipelines.actions.githubusercontent.com/fLgcSHkPGySXeIFrg8W8OBSfeg3b5Fls1A1CwX566g8PayEGlg/ // TODO: this prefix should be generated with a token string with runner ? prefix = "/api/actions_pipeline" - r.Mount(prefix, actions_router.ArtifactsRoutes(ctx, prefix)) + r.Mount(prefix, actions_router.ArtifactsRoutes(prefix)) } return r diff --git a/routers/install/install.go b/routers/install/install.go index 714ddd5548..89b91a5a48 100644 --- a/routers/install/install.go +++ b/routers/install/install.go @@ -58,15 +58,14 @@ func Contexter() func(next http.Handler) http.Handler { dbTypeNames := getSupportedDbTypeNames() return func(next http.Handler) http.Handler { return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { + base, baseCleanUp := context.NewBaseContext(resp, req) ctx := context.Context{ - Resp: context.NewResponse(resp), + Base: base, Flash: &middleware.Flash{}, - Locale: middleware.Locale(resp, req), Render: rnd, - Data: middleware.GetContextData(req.Context()), Session: session.GetSession(req), } - defer ctx.Close() + defer baseCleanUp() ctx.Data.MergeFrom(middleware.CommonTemplateContextData()) ctx.Data.MergeFrom(middleware.ContextData{ @@ -78,7 +77,6 @@ func Contexter() func(next http.Handler) http.Handler { "PasswordHashAlgorithms": hash.RecommendedHashAlgorithms, }) - ctx.Req = context.WithContext(req, &ctx) next.ServeHTTP(resp, ctx.Req) }) } @@ -249,15 +247,8 @@ func SubmitInstall(ctx *context.Context) { ctx.Data["CurDbType"] = form.DbType if ctx.HasError() { - if ctx.HasValue("Err_SMTPUser") { - ctx.Data["Err_SMTP"] = true - } - if ctx.HasValue("Err_AdminName") || - ctx.HasValue("Err_AdminPasswd") || - ctx.HasValue("Err_AdminEmail") { - ctx.Data["Err_Admin"] = true - } - + ctx.Data["Err_SMTP"] = ctx.Data["Err_SMTPUser"] != nil + ctx.Data["Err_Admin"] = ctx.Data["Err_AdminName"] != nil || ctx.Data["Err_AdminPasswd"] != nil || ctx.Data["Err_AdminEmail"] != nil ctx.HTML(http.StatusOK, tplInstall) return } diff --git a/routers/web/misc/markup.go b/routers/web/misc/markup.go index 1690378945..c91da9a7f1 100644 --- a/routers/web/misc/markup.go +++ b/routers/web/misc/markup.go @@ -5,8 +5,6 @@ package misc import ( - "net/http" - "code.gitea.io/gitea/modules/context" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/modules/web" @@ -16,11 +14,5 @@ import ( // Markup render markup document to HTML func Markup(ctx *context.Context) { form := web.GetForm(ctx).(*api.MarkupOption) - - if ctx.HasAPIError() { - ctx.Error(http.StatusUnprocessableEntity, "", ctx.GetErrMsg()) - return - } - - common.RenderMarkup(ctx, form.Mode, form.Text, form.Context, form.FilePath, form.Wiki) + common.RenderMarkup(ctx.Base, ctx.Repo, form.Mode, form.Text, form.Context, form.FilePath, form.Wiki) } diff --git a/routers/web/repo/attachment.go b/routers/web/repo/attachment.go index c46ec29841..fb95e63ecf 100644 --- a/routers/web/repo/attachment.go +++ b/routers/web/repo/attachment.go @@ -153,7 +153,7 @@ func ServeAttachment(ctx *context.Context, uuid string) { } defer fr.Close() - common.ServeContentByReadSeeker(ctx, attach.Name, attach.CreatedUnix.AsTime(), fr) + common.ServeContentByReadSeeker(ctx.Base, attach.Name, attach.CreatedUnix.AsTime(), fr) } // GetAttachment serve attachments diff --git a/routers/web/repo/download.go b/routers/web/repo/download.go index 1c87f9bed7..a498180f35 100644 --- a/routers/web/repo/download.go +++ b/routers/web/repo/download.go @@ -47,7 +47,7 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob, lastModified time.Time log.Error("ServeBlobOrLFS: Close: %v", err) } closed = true - return common.ServeBlob(ctx, blob, lastModified) + return common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, lastModified) } if httpcache.HandleGenericETagCache(ctx.Req, ctx.Resp, `"`+pointer.Oid+`"`) { return nil @@ -71,7 +71,7 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob, lastModified time.Time log.Error("ServeBlobOrLFS: Close: %v", err) } }() - common.ServeContentByReadSeeker(ctx, ctx.Repo.TreePath, lastModified, lfsDataRc) + common.ServeContentByReadSeeker(ctx.Base, ctx.Repo.TreePath, lastModified, lfsDataRc) return nil } if err = dataRc.Close(); err != nil { @@ -79,7 +79,7 @@ func ServeBlobOrLFS(ctx *context.Context, blob *git.Blob, lastModified time.Time } closed = true - return common.ServeBlob(ctx, blob, lastModified) + return common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, lastModified) } func getBlobForEntry(ctx *context.Context) (blob *git.Blob, lastModified time.Time) { @@ -120,7 +120,7 @@ func SingleDownload(ctx *context.Context) { return } - if err := common.ServeBlob(ctx, blob, lastModified); err != nil { + if err := common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, lastModified); err != nil { ctx.ServerError("ServeBlob", err) } } @@ -148,7 +148,7 @@ func DownloadByID(ctx *context.Context) { } return } - if err = common.ServeBlob(ctx, blob, time.Time{}); err != nil { + if err = common.ServeBlob(ctx.Base, ctx.Repo.TreePath, blob, time.Time{}); err != nil { ctx.ServerError("ServeBlob", err) } } diff --git a/routers/web/repo/http.go b/routers/web/repo/http.go index 4e45a9b6e2..b6ebd25915 100644 --- a/routers/web/repo/http.go +++ b/routers/web/repo/http.go @@ -109,7 +109,7 @@ func httpBase(ctx *context.Context) (h *serviceHandler) { if err != nil { if repo_model.IsErrRepoNotExist(err) { if redirectRepoID, err := repo_model.LookupRedirect(owner.ID, reponame); err == nil { - context.RedirectToRepo(ctx, redirectRepoID) + context.RedirectToRepo(ctx.Base, redirectRepoID) return } repoExist = false diff --git a/routers/web/repo/issue.go b/routers/web/repo/issue.go index 88d2a97a7a..7a0dc9940b 100644 --- a/routers/web/repo/issue.go +++ b/routers/web/repo/issue.go @@ -2344,7 +2344,7 @@ func UpdatePullReviewRequest(ctx *context.Context) { // SearchIssues searches for issues across the repositories that the user has access to func SearchIssues(ctx *context.Context) { - before, since, err := context.GetQueryBeforeSince(ctx) + before, since, err := context.GetQueryBeforeSince(ctx.Base) if err != nil { ctx.Error(http.StatusUnprocessableEntity, err.Error()) return @@ -2545,7 +2545,7 @@ func getUserIDForFilter(ctx *context.Context, queryName string) int64 { // ListIssues list the issues of a repository func ListIssues(ctx *context.Context) { - before, since, err := context.GetQueryBeforeSince(ctx) + before, since, err := context.GetQueryBeforeSince(ctx.Base) if err != nil { ctx.Error(http.StatusUnprocessableEntity, err.Error()) return diff --git a/routers/web/repo/wiki.go b/routers/web/repo/wiki.go index a335c114be..115418887d 100644 --- a/routers/web/repo/wiki.go +++ b/routers/web/repo/wiki.go @@ -671,7 +671,7 @@ func WikiRaw(ctx *context.Context) { } if entry != nil { - if err = common.ServeBlob(ctx, entry.Blob(), time.Time{}); err != nil { + if err = common.ServeBlob(ctx.Base, ctx.Repo.TreePath, entry.Blob(), time.Time{}); err != nil { ctx.ServerError("ServeBlob", err) } return |