code.gitea.io/gitea@v1.19.3/modules/web/wrap.go (about) 1 // Copyright 2021 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package web 5 6 import ( 7 goctx "context" 8 "net/http" 9 "strings" 10 11 "code.gitea.io/gitea/modules/context" 12 "code.gitea.io/gitea/modules/web/routing" 13 ) 14 15 // Wrap converts all kinds of routes to standard library one 16 func Wrap(handlers ...interface{}) http.HandlerFunc { 17 if len(handlers) == 0 { 18 panic("No handlers found") 19 } 20 21 ourHandlers := make([]wrappedHandlerFunc, 0, len(handlers)) 22 23 for _, handler := range handlers { 24 ourHandlers = append(ourHandlers, convertHandler(handler)) 25 } 26 return wrapInternal(ourHandlers) 27 } 28 29 func wrapInternal(handlers []wrappedHandlerFunc) http.HandlerFunc { 30 return func(resp http.ResponseWriter, req *http.Request) { 31 var defers []func() 32 defer func() { 33 for i := len(defers) - 1; i >= 0; i-- { 34 defers[i]() 35 } 36 }() 37 for i := 0; i < len(handlers); i++ { 38 handler := handlers[i] 39 others := handlers[i+1:] 40 done, deferrable := handler(resp, req, others...) 41 if deferrable != nil { 42 defers = append(defers, deferrable) 43 } 44 if done { 45 return 46 } 47 } 48 } 49 } 50 51 // Middle wrap a context function as a chi middleware 52 func Middle(f func(ctx *context.Context)) func(next http.Handler) http.Handler { 53 funcInfo := routing.GetFuncInfo(f) 54 return func(next http.Handler) http.Handler { 55 return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 56 routing.UpdateFuncInfo(req.Context(), funcInfo) 57 ctx := context.GetContext(req) 58 f(ctx) 59 if ctx.Written() { 60 return 61 } 62 next.ServeHTTP(ctx.Resp, ctx.Req) 63 }) 64 } 65 } 66 67 // MiddleCancel wrap a context function as a chi middleware 68 func MiddleCancel(f func(ctx *context.Context) goctx.CancelFunc) func(netx http.Handler) http.Handler { 69 funcInfo := routing.GetFuncInfo(f) 70 return func(next http.Handler) http.Handler { 71 return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 72 routing.UpdateFuncInfo(req.Context(), funcInfo) 73 ctx := context.GetContext(req) 74 cancel := f(ctx) 75 if cancel != nil { 76 defer cancel() 77 } 78 if ctx.Written() { 79 return 80 } 81 next.ServeHTTP(ctx.Resp, ctx.Req) 82 }) 83 } 84 } 85 86 // MiddleAPI wrap a context function as a chi middleware 87 func MiddleAPI(f func(ctx *context.APIContext)) func(next http.Handler) http.Handler { 88 funcInfo := routing.GetFuncInfo(f) 89 return func(next http.Handler) http.Handler { 90 return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 91 routing.UpdateFuncInfo(req.Context(), funcInfo) 92 ctx := context.GetAPIContext(req) 93 f(ctx) 94 if ctx.Written() { 95 return 96 } 97 next.ServeHTTP(ctx.Resp, ctx.Req) 98 }) 99 } 100 } 101 102 // WrapWithPrefix wraps a provided handler function at a prefix 103 func WrapWithPrefix(pathPrefix string, handler http.HandlerFunc, friendlyName ...string) func(next http.Handler) http.Handler { 104 funcInfo := routing.GetFuncInfo(handler, friendlyName...) 105 106 return func(next http.Handler) http.Handler { 107 return http.HandlerFunc(func(resp http.ResponseWriter, req *http.Request) { 108 if !strings.HasPrefix(req.URL.Path, pathPrefix) { 109 next.ServeHTTP(resp, req) 110 return 111 } 112 routing.UpdateFuncInfo(req.Context(), funcInfo) 113 handler(resp, req) 114 }) 115 } 116 }