You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

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