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  }