2021-01-26 18:36:53 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2021-01-26 18:36:53 +03:00
package context
import (
"context"
2022-01-20 02:26:57 +03:00
"fmt"
2021-01-26 18:36:53 +03:00
"net/http"
2022-01-20 02:26:57 +03:00
"time"
"code.gitea.io/gitea/modules/graceful"
"code.gitea.io/gitea/modules/process"
2023-06-18 10:59:09 +03:00
"code.gitea.io/gitea/modules/web"
web_types "code.gitea.io/gitea/modules/web/types"
2021-01-26 18:36:53 +03:00
)
// PrivateContext represents a context for private routes
type PrivateContext struct {
2023-05-21 04:50:53 +03:00
* Base
2022-01-20 02:26:57 +03:00
Override context . Context
2023-05-21 04:50:53 +03:00
Repo * Repository
2022-01-20 02:26:57 +03:00
}
2023-06-18 10:59:09 +03:00
func init ( ) {
web . RegisterResponseStatusProvider [ * PrivateContext ] ( func ( req * http . Request ) web_types . ResponseStatusProvider {
return req . Context ( ) . Value ( privateContextKey ) . ( * PrivateContext )
} )
}
2022-01-20 02:26:57 +03:00
// Deadline is part of the interface for context.Context and we pass this to the request context
func ( ctx * PrivateContext ) Deadline ( ) ( deadline time . Time , ok bool ) {
if ctx . Override != nil {
return ctx . Override . Deadline ( )
}
2023-05-21 04:50:53 +03:00
return ctx . Base . Deadline ( )
2022-01-20 02:26:57 +03:00
}
// Done is part of the interface for context.Context and we pass this to the request context
func ( ctx * PrivateContext ) Done ( ) <- chan struct { } {
if ctx . Override != nil {
return ctx . Override . Done ( )
}
2023-05-21 04:50:53 +03:00
return ctx . Base . Done ( )
2022-01-20 02:26:57 +03:00
}
// Err is part of the interface for context.Context and we pass this to the request context
func ( ctx * PrivateContext ) Err ( ) error {
if ctx . Override != nil {
return ctx . Override . Err ( )
}
2023-05-21 04:50:53 +03:00
return ctx . Base . Err ( )
2021-01-26 18:36:53 +03:00
}
2023-07-04 21:36:08 +03:00
var privateContextKey any = "default_private_context"
2021-01-26 18:36:53 +03:00
// GetPrivateContext returns a context for Private routes
func GetPrivateContext ( req * http . Request ) * PrivateContext {
return req . Context ( ) . Value ( privateContextKey ) . ( * PrivateContext )
}
2021-01-29 18:35:30 +03:00
// PrivateContexter returns apicontext as middleware
2021-01-26 18:36:53 +03:00
func PrivateContexter ( ) func ( http . Handler ) http . Handler {
return func ( next http . Handler ) http . Handler {
return http . HandlerFunc ( func ( w http . ResponseWriter , req * http . Request ) {
2023-05-21 04:50:53 +03:00
base , baseCleanUp := NewBaseContext ( w , req )
ctx := & PrivateContext { Base : base }
defer baseCleanUp ( )
ctx . Base . AppendContextValue ( privateContextKey , ctx )
2022-05-05 17:13:23 +03:00
2021-01-26 18:36:53 +03:00
next . ServeHTTP ( ctx . Resp , ctx . Req )
} )
}
}
2022-01-20 02:26:57 +03:00
// 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 ( ctx * PrivateContext ) ( cancel context . CancelFunc ) {
// 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
2022-03-31 20:01:43 +03:00
ctx . Override , _ , cancel = process . GetManager ( ) . AddTypedContext ( graceful . GetManager ( ) . HammerContext ( ) , fmt . Sprintf ( "PrivateContext: %s" , ctx . Req . RequestURI ) , process . RequestProcessType , true )
2022-06-20 13:02:49 +03:00
return cancel
2022-01-20 02:26:57 +03:00
}