2021-01-26 18:36:53 +03:00
// Copyright 2020 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
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"
2021-01-26 18:36:53 +03:00
)
// PrivateContext represents a context for private routes
type PrivateContext struct {
* Context
2022-01-20 02:26:57 +03:00
Override context . Context
}
// 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 ( )
}
return ctx . Req . Context ( ) . Deadline ( )
}
// 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 ( )
}
return ctx . Req . Context ( ) . Done ( )
}
// 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 ( )
}
return ctx . Req . Context ( ) . Err ( )
2021-01-26 18:36:53 +03:00
}
2022-01-20 20:46:10 +03:00
var privateContextKey interface { } = "default_private_context"
2021-01-26 18:36:53 +03:00
// WithPrivateContext set up private context in request
func WithPrivateContext ( req * http . Request , ctx * PrivateContext ) * http . Request {
return req . WithContext ( context . WithValue ( req . Context ( ) , privateContextKey , ctx ) )
}
// 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 ) {
ctx := & PrivateContext {
Context : & Context {
Resp : NewResponse ( w ) ,
Data : map [ string ] interface { } { } ,
} ,
}
2022-05-05 17:13:23 +03:00
defer ctx . Close ( )
2021-01-26 18:36:53 +03:00
ctx . Req = WithPrivateContext ( req , ctx )
2022-01-20 02:26:57 +03:00
ctx . Data [ "Context" ] = ctx
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
}