adapter.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. package fiber
  2. import (
  3. "fmt"
  4. "net/http"
  5. "reflect"
  6. "github.com/valyala/fasthttp"
  7. "github.com/valyala/fasthttp/fasthttpadaptor"
  8. )
  9. // toFiberHandler converts a supported handler type to a Fiber handler.
  10. func toFiberHandler(handler any) (Handler, bool) {
  11. if handler == nil {
  12. return nil, false
  13. }
  14. switch handler.(type) {
  15. case Handler, func(Ctx): // (1)-(2) Fiber handlers
  16. return adaptFiberHandler(handler)
  17. case func(Req, Res) error, func(Req, Res), func(Req, Res, func() error) error, func(Req, Res, func() error), func(Req, Res, func()) error, func(Req, Res, func()), func(Req, Res, func(error)), func(Req, Res, func(error)) error, func(Req, Res, func(error) error), func(Req, Res, func(error) error) error: // (3)-(12) Express-style request handlers
  18. return adaptExpressHandler(handler)
  19. case http.HandlerFunc, http.Handler, func(http.ResponseWriter, *http.Request): // (13)-(15) net/http handlers
  20. return adaptHTTPHandler(handler)
  21. case fasthttp.RequestHandler, func(*fasthttp.RequestCtx) error: // (16)-(17) fasthttp handlers
  22. return adaptFastHTTPHandler(handler)
  23. default: // (18) unsupported handler type
  24. return nil, false
  25. }
  26. }
  27. func adaptFiberHandler(handler any) (Handler, bool) {
  28. switch h := handler.(type) {
  29. case Handler: // (1) direct Fiber handler
  30. if h == nil {
  31. return nil, false
  32. }
  33. return h, true
  34. case func(Ctx): // (2) Fiber handler without error return
  35. if h == nil {
  36. return nil, false
  37. }
  38. return func(c Ctx) error {
  39. h(c)
  40. return nil
  41. }, true
  42. default:
  43. return nil, false
  44. }
  45. }
  46. func adaptExpressHandler(handler any) (Handler, bool) {
  47. switch h := handler.(type) {
  48. case func(Req, Res) error: // (3) Express-style handler with error return
  49. if h == nil {
  50. return nil, false
  51. }
  52. return func(c Ctx) error {
  53. return h(c.Req(), c.Res())
  54. }, true
  55. case func(Req, Res): // (4) Express-style handler without error return
  56. if h == nil {
  57. return nil, false
  58. }
  59. return func(c Ctx) error {
  60. h(c.Req(), c.Res())
  61. return nil
  62. }, true
  63. case func(Req, Res, func() error) error: // (5) Express-style handler with error-returning next callback and error return
  64. if h == nil {
  65. return nil, false
  66. }
  67. return func(c Ctx) error {
  68. return h(c.Req(), c.Res(), func() error {
  69. return c.Next()
  70. })
  71. }, true
  72. case func(Req, Res, func() error): // (6) Express-style handler with error-returning next callback
  73. if h == nil {
  74. return nil, false
  75. }
  76. return func(c Ctx) error {
  77. var nextErr error
  78. h(c.Req(), c.Res(), func() error {
  79. nextErr = c.Next()
  80. return nextErr
  81. })
  82. return nextErr
  83. }, true
  84. case func(Req, Res, func()) error: // (7) Express-style handler with no-arg next callback and error return
  85. if h == nil {
  86. return nil, false
  87. }
  88. return func(c Ctx) error {
  89. var nextErr error
  90. err := h(c.Req(), c.Res(), func() {
  91. nextErr = c.Next()
  92. })
  93. if err != nil {
  94. return err
  95. }
  96. return nextErr
  97. }, true
  98. case func(Req, Res, func()): // (8) Express-style handler with no-arg next callback
  99. if h == nil {
  100. return nil, false
  101. }
  102. return func(c Ctx) error {
  103. var nextErr error
  104. h(c.Req(), c.Res(), func() {
  105. nextErr = c.Next()
  106. })
  107. return nextErr
  108. }, true
  109. case func(Req, Res, func(error)): // (9) Express-style handler with error-accepting next callback
  110. if h == nil {
  111. return nil, false
  112. }
  113. return func(c Ctx) error {
  114. var nextErr error
  115. h(c.Req(), c.Res(), func(err error) {
  116. if err != nil {
  117. nextErr = err
  118. return
  119. }
  120. nextErr = c.Next()
  121. })
  122. return nextErr
  123. }, true
  124. case func(Req, Res, func(error)) error: // (10) Express-style handler with error-accepting next callback and error return
  125. if h == nil {
  126. return nil, false
  127. }
  128. return func(c Ctx) error {
  129. var nextErr error
  130. err := h(c.Req(), c.Res(), func(nextErrArg error) {
  131. if nextErrArg != nil {
  132. nextErr = nextErrArg
  133. return
  134. }
  135. nextErr = c.Next()
  136. })
  137. if err != nil {
  138. return err
  139. }
  140. return nextErr
  141. }, true
  142. case func(Req, Res, func(error) error): // (11) Express-style handler with error-accepting next callback that returns an error
  143. if h == nil {
  144. return nil, false
  145. }
  146. return func(c Ctx) error {
  147. var nextErr error
  148. h(c.Req(), c.Res(), func(nextErrArg error) error {
  149. if nextErrArg != nil {
  150. nextErr = nextErrArg
  151. return nextErrArg
  152. }
  153. nextErr = c.Next()
  154. return nextErr
  155. })
  156. return nextErr
  157. }, true
  158. case func(Req, Res, func(error) error) error: // (12) Express-style handler with error-accepting next callback that returns an error and error return
  159. if h == nil {
  160. return nil, false
  161. }
  162. return func(c Ctx) error {
  163. var nextErr error
  164. err := h(c.Req(), c.Res(), func(nextErrArg error) error {
  165. if nextErrArg != nil {
  166. nextErr = nextErrArg
  167. return nextErrArg
  168. }
  169. nextErr = c.Next()
  170. return nextErr
  171. })
  172. if err != nil {
  173. return err
  174. }
  175. return nextErr
  176. }, true
  177. default:
  178. return nil, false
  179. }
  180. }
  181. func adaptHTTPHandler(handler any) (Handler, bool) {
  182. switch h := handler.(type) {
  183. case http.HandlerFunc: // (13) net/http HandlerFunc
  184. if h == nil {
  185. return nil, false
  186. }
  187. return wrapHTTPHandler(h), true
  188. case http.Handler: // (14) net/http Handler implementation
  189. if h == nil {
  190. return nil, false
  191. }
  192. hv := reflect.ValueOf(h)
  193. if isNilableKind(hv.Kind()) && hv.IsNil() {
  194. return nil, false
  195. }
  196. return wrapHTTPHandler(h), true
  197. case func(http.ResponseWriter, *http.Request): // (15) net/http function handler
  198. if h == nil {
  199. return nil, false
  200. }
  201. return wrapHTTPHandler(http.HandlerFunc(h)), true
  202. default:
  203. return nil, false
  204. }
  205. }
  206. func isNilableKind(kind reflect.Kind) bool {
  207. switch kind {
  208. case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.Interface, reflect.Slice, reflect.UnsafePointer:
  209. return true
  210. default:
  211. return false
  212. }
  213. }
  214. func adaptFastHTTPHandler(handler any) (Handler, bool) {
  215. switch h := handler.(type) {
  216. case fasthttp.RequestHandler: // (16) fasthttp handler
  217. if h == nil {
  218. return nil, false
  219. }
  220. return func(c Ctx) error {
  221. h(c.RequestCtx())
  222. return nil
  223. }, true
  224. case func(*fasthttp.RequestCtx) error: // (17) fasthttp handler with error return
  225. if h == nil {
  226. return nil, false
  227. }
  228. return func(c Ctx) error {
  229. return h(c.RequestCtx())
  230. }, true
  231. default:
  232. return nil, false
  233. }
  234. }
  235. // wrapHTTPHandler adapts a net/http handler to a Fiber handler.
  236. func wrapHTTPHandler(handler http.Handler) Handler {
  237. if handler == nil {
  238. return nil
  239. }
  240. adapted := fasthttpadaptor.NewFastHTTPHandler(handler)
  241. return func(c Ctx) error {
  242. adapted(c.RequestCtx())
  243. return nil
  244. }
  245. }
  246. // collectHandlers converts a slice of handler arguments to Fiber handlers.
  247. // The context string is used to provide informative panic messages when an
  248. // unsupported handler type is encountered.
  249. func collectHandlers(context string, args ...any) []Handler {
  250. handlers := make([]Handler, 0, len(args))
  251. for i, arg := range args {
  252. handler, ok := toFiberHandler(arg)
  253. if !ok {
  254. panic(fmt.Sprintf("%s: invalid handler #%d (%T)\n", context, i, arg))
  255. }
  256. handlers = append(handlers, handler)
  257. }
  258. return handlers
  259. }