mirror of
https://github.com/hanzoai/forge.git
synced 2026-10-30 15:00:39 +00:00
Source files keep their SPDX-License-Identifier and Hanzo copyright line; the Gitea, Gogs and LFS Test Server copyrights they used to repeat now live once in NOTICE, alongside LICENSE. The header lint accepts any copyright line above the SPDX line, so it no longer demands an upstream one. Co-authored-by: Hanzo Dev <[email protected]>
96 lines
2.8 KiB
Go
96 lines
2.8 KiB
Go
// Copyright 2026 Hanzo AI, Inc. All rights reserved.
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
package context
|
|
|
|
import (
|
|
"context"
|
|
"net/http"
|
|
"time"
|
|
|
|
"github.com/hanzoai/git/modules/graceful"
|
|
"github.com/hanzoai/git/modules/private"
|
|
"github.com/hanzoai/git/modules/process"
|
|
"github.com/hanzoai/git/modules/web"
|
|
web_types "github.com/hanzoai/git/modules/web/types"
|
|
)
|
|
|
|
// PrivateContext represents a context for private routes
|
|
type PrivateContext struct {
|
|
*Base
|
|
Override context.Context
|
|
|
|
Repo *Repository
|
|
}
|
|
|
|
func init() {
|
|
web.RegisterResponseStatusProvider[*PrivateContext](func(req *http.Request) web_types.ResponseStatusProvider {
|
|
return req.Context().Value(privateContextKey).(*PrivateContext)
|
|
})
|
|
}
|
|
|
|
func (ctx *PrivateContext) Deadline() (deadline time.Time, ok bool) {
|
|
if ctx.Override != nil {
|
|
return ctx.Override.Deadline()
|
|
}
|
|
return ctx.Base.Deadline()
|
|
}
|
|
|
|
func (ctx *PrivateContext) Done() <-chan struct{} {
|
|
if ctx.Override != nil {
|
|
return ctx.Override.Done()
|
|
}
|
|
return ctx.Base.Done()
|
|
}
|
|
|
|
func (ctx *PrivateContext) Err() error {
|
|
if ctx.Override != nil {
|
|
return ctx.Override.Err()
|
|
}
|
|
return ctx.Base.Err()
|
|
}
|
|
|
|
func (ctx *PrivateContext) PrivateError(status int, err error, userMsg string) {
|
|
errMsg := ""
|
|
if err != nil {
|
|
errMsg = err.Error()
|
|
}
|
|
ctx.JSON(status, private.Response{Err: errMsg, UserMsg: userMsg})
|
|
}
|
|
|
|
type privateContextKeyType struct{}
|
|
|
|
var privateContextKey privateContextKeyType
|
|
|
|
func GetPrivateContext(req *http.Request) *PrivateContext {
|
|
return req.Context().Value(privateContextKey).(*PrivateContext)
|
|
}
|
|
|
|
func PrivateContexter() func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
base := NewBaseContext(w, req)
|
|
ctx := &PrivateContext{Base: base}
|
|
ctx.SetContextValue(privateContextKey, ctx)
|
|
next.ServeHTTP(ctx.Resp, ctx.Req)
|
|
})
|
|
}
|
|
}
|
|
|
|
// OverrideContext overrides the underlying request context for Done() etc.
|
|
// This function should be used when there is a need for work to continue even if the request has been cancelled.
|
|
// Primarily this affects hook/post-receive and hook/proc-receive both of which need to continue working even if
|
|
// the underlying request has timed out from the ssh/http push
|
|
func OverrideContext() func(http.Handler) http.Handler {
|
|
return func(next http.Handler) http.Handler {
|
|
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
|
|
// We now need to override the request context as the base for our work because even if the request is cancelled we have to continue this work
|
|
ctx := GetPrivateContext(req)
|
|
var finished func()
|
|
ctx.Override, _, finished = process.GetManager().AddTypedContext(graceful.GetManager().HammerContext(), "PrivateContext: "+ctx.Req.RequestURI, process.RequestProcessType, true)
|
|
defer finished()
|
|
next.ServeHTTP(ctx.Resp, ctx.Req)
|
|
})
|
|
}
|
|
}
|