1
0
Fork 0
forked from forgejo/forgejo

Refactor web package and context package (#25298)

1. The "web" package shouldn't depends on "modules/context" package,
instead, let each "web context" register themselves to the "web"
package.
2. The old Init/Free doesn't make sense, so simplify it
* The ctx in "Init(ctx)" is never used, and shouldn't be used that way
* The "Free" is never called and shouldn't be called because the SSPI
instance is shared

---------

Co-authored-by: Giteabot <teabot@gitea.io>
This commit is contained in:
wxiaoguang 2023-06-18 15:59:09 +08:00 committed by GitHub
parent fc2115b494
commit 4e2f1ee58d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
45 changed files with 218 additions and 292 deletions

View file

@ -9,25 +9,15 @@ import (
"net/http"
"reflect"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/web/routing"
"code.gitea.io/gitea/modules/web/types"
)
// ResponseStatusProvider is an interface to check whether the response has been written by the handler
type ResponseStatusProvider interface {
Written() bool
}
var responseStatusProviders = map[reflect.Type]func(req *http.Request) types.ResponseStatusProvider{}
// TODO: decouple this from the context package, let the context package register these providers
var argTypeProvider = map[reflect.Type]func(req *http.Request) ResponseStatusProvider{
reflect.TypeOf(&context.APIContext{}): func(req *http.Request) ResponseStatusProvider { return context.GetAPIContext(req) },
reflect.TypeOf(&context.Context{}): func(req *http.Request) ResponseStatusProvider { return context.GetWebContext(req) },
reflect.TypeOf(&context.PrivateContext{}): func(req *http.Request) ResponseStatusProvider { return context.GetPrivateContext(req) },
}
func RegisterHandleTypeProvider[T any](fn func(req *http.Request) ResponseStatusProvider) {
argTypeProvider[reflect.TypeOf((*T)(nil)).Elem()] = fn
func RegisterResponseStatusProvider[T any](fn func(req *http.Request) types.ResponseStatusProvider) {
responseStatusProviders[reflect.TypeOf((*T)(nil)).Elem()] = fn
}
// responseWriter is a wrapper of http.ResponseWriter, to check whether the response has been written
@ -36,10 +26,10 @@ type responseWriter struct {
status int
}
var _ ResponseStatusProvider = (*responseWriter)(nil)
var _ types.ResponseStatusProvider = (*responseWriter)(nil)
func (r *responseWriter) Written() bool {
return r.status > 0
func (r *responseWriter) WrittenStatus() int {
return r.status
}
func (r *responseWriter) Header() http.Header {
@ -68,7 +58,7 @@ var (
func preCheckHandler(fn reflect.Value, argsIn []reflect.Value) {
hasStatusProvider := false
for _, argIn := range argsIn {
if _, hasStatusProvider = argIn.Interface().(ResponseStatusProvider); hasStatusProvider {
if _, hasStatusProvider = argIn.Interface().(types.ResponseStatusProvider); hasStatusProvider {
break
}
}
@ -101,7 +91,7 @@ func prepareHandleArgsIn(resp http.ResponseWriter, req *http.Request, fn reflect
case httpReqType:
argsIn[i] = reflect.ValueOf(req)
default:
if argFn, ok := argTypeProvider[argTyp]; ok {
if argFn, ok := responseStatusProviders[argTyp]; ok {
if isPreCheck {
argsIn[i] = reflect.ValueOf(&responseWriter{})
} else {
@ -129,8 +119,8 @@ func handleResponse(fn reflect.Value, ret []reflect.Value) goctx.CancelFunc {
func hasResponseBeenWritten(argsIn []reflect.Value) bool {
for _, argIn := range argsIn {
if statusProvider, ok := argIn.Interface().(ResponseStatusProvider); ok {
if statusProvider.Written() {
if statusProvider, ok := argIn.Interface().(types.ResponseStatusProvider); ok {
if statusProvider.WrittenStatus() != 0 {
return true
}
}
@ -161,7 +151,7 @@ func toHandlerProvider(handler any) func(next http.Handler) http.Handler {
return http.HandlerFunc(func(respOrig http.ResponseWriter, req *http.Request) {
// wrap the response writer to check whether the response has been written
resp := respOrig
if _, ok := resp.(ResponseStatusProvider); !ok {
if _, ok := resp.(types.ResponseStatusProvider); !ok {
resp = &responseWriter{respWriter: resp}
}