| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275 |
- package fiber
- import (
- "fmt"
- "net/http"
- "reflect"
- "github.com/valyala/fasthttp"
- "github.com/valyala/fasthttp/fasthttpadaptor"
- )
- // toFiberHandler converts a supported handler type to a Fiber handler.
- func toFiberHandler(handler any) (Handler, bool) {
- if handler == nil {
- return nil, false
- }
- switch handler.(type) {
- case Handler, func(Ctx): // (1)-(2) Fiber handlers
- return adaptFiberHandler(handler)
- 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
- return adaptExpressHandler(handler)
- case http.HandlerFunc, http.Handler, func(http.ResponseWriter, *http.Request): // (13)-(15) net/http handlers
- return adaptHTTPHandler(handler)
- case fasthttp.RequestHandler, func(*fasthttp.RequestCtx) error: // (16)-(17) fasthttp handlers
- return adaptFastHTTPHandler(handler)
- default: // (18) unsupported handler type
- return nil, false
- }
- }
- func adaptFiberHandler(handler any) (Handler, bool) {
- switch h := handler.(type) {
- case Handler: // (1) direct Fiber handler
- if h == nil {
- return nil, false
- }
- return h, true
- case func(Ctx): // (2) Fiber handler without error return
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- h(c)
- return nil
- }, true
- default:
- return nil, false
- }
- }
- func adaptExpressHandler(handler any) (Handler, bool) {
- switch h := handler.(type) {
- case func(Req, Res) error: // (3) Express-style handler with error return
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- return h(c.Req(), c.Res())
- }, true
- case func(Req, Res): // (4) Express-style handler without error return
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- h(c.Req(), c.Res())
- return nil
- }, true
- case func(Req, Res, func() error) error: // (5) Express-style handler with error-returning next callback and error return
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- return h(c.Req(), c.Res(), func() error {
- return c.Next()
- })
- }, true
- case func(Req, Res, func() error): // (6) Express-style handler with error-returning next callback
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- var nextErr error
- h(c.Req(), c.Res(), func() error {
- nextErr = c.Next()
- return nextErr
- })
- return nextErr
- }, true
- case func(Req, Res, func()) error: // (7) Express-style handler with no-arg next callback and error return
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- var nextErr error
- err := h(c.Req(), c.Res(), func() {
- nextErr = c.Next()
- })
- if err != nil {
- return err
- }
- return nextErr
- }, true
- case func(Req, Res, func()): // (8) Express-style handler with no-arg next callback
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- var nextErr error
- h(c.Req(), c.Res(), func() {
- nextErr = c.Next()
- })
- return nextErr
- }, true
- case func(Req, Res, func(error)): // (9) Express-style handler with error-accepting next callback
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- var nextErr error
- h(c.Req(), c.Res(), func(err error) {
- if err != nil {
- nextErr = err
- return
- }
- nextErr = c.Next()
- })
- return nextErr
- }, true
- case func(Req, Res, func(error)) error: // (10) Express-style handler with error-accepting next callback and error return
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- var nextErr error
- err := h(c.Req(), c.Res(), func(nextErrArg error) {
- if nextErrArg != nil {
- nextErr = nextErrArg
- return
- }
- nextErr = c.Next()
- })
- if err != nil {
- return err
- }
- return nextErr
- }, true
- case func(Req, Res, func(error) error): // (11) Express-style handler with error-accepting next callback that returns an error
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- var nextErr error
- h(c.Req(), c.Res(), func(nextErrArg error) error {
- if nextErrArg != nil {
- nextErr = nextErrArg
- return nextErrArg
- }
- nextErr = c.Next()
- return nextErr
- })
- return nextErr
- }, true
- case func(Req, Res, func(error) error) error: // (12) Express-style handler with error-accepting next callback that returns an error and error return
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- var nextErr error
- err := h(c.Req(), c.Res(), func(nextErrArg error) error {
- if nextErrArg != nil {
- nextErr = nextErrArg
- return nextErrArg
- }
- nextErr = c.Next()
- return nextErr
- })
- if err != nil {
- return err
- }
- return nextErr
- }, true
- default:
- return nil, false
- }
- }
- func adaptHTTPHandler(handler any) (Handler, bool) {
- switch h := handler.(type) {
- case http.HandlerFunc: // (13) net/http HandlerFunc
- if h == nil {
- return nil, false
- }
- return wrapHTTPHandler(h), true
- case http.Handler: // (14) net/http Handler implementation
- if h == nil {
- return nil, false
- }
- hv := reflect.ValueOf(h)
- if isNilableKind(hv.Kind()) && hv.IsNil() {
- return nil, false
- }
- return wrapHTTPHandler(h), true
- case func(http.ResponseWriter, *http.Request): // (15) net/http function handler
- if h == nil {
- return nil, false
- }
- return wrapHTTPHandler(http.HandlerFunc(h)), true
- default:
- return nil, false
- }
- }
- func isNilableKind(kind reflect.Kind) bool {
- switch kind {
- case reflect.Chan, reflect.Func, reflect.Map, reflect.Pointer, reflect.Interface, reflect.Slice, reflect.UnsafePointer:
- return true
- default:
- return false
- }
- }
- func adaptFastHTTPHandler(handler any) (Handler, bool) {
- switch h := handler.(type) {
- case fasthttp.RequestHandler: // (16) fasthttp handler
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- h(c.RequestCtx())
- return nil
- }, true
- case func(*fasthttp.RequestCtx) error: // (17) fasthttp handler with error return
- if h == nil {
- return nil, false
- }
- return func(c Ctx) error {
- return h(c.RequestCtx())
- }, true
- default:
- return nil, false
- }
- }
- // wrapHTTPHandler adapts a net/http handler to a Fiber handler.
- func wrapHTTPHandler(handler http.Handler) Handler {
- if handler == nil {
- return nil
- }
- adapted := fasthttpadaptor.NewFastHTTPHandler(handler)
- return func(c Ctx) error {
- adapted(c.RequestCtx())
- return nil
- }
- }
- // collectHandlers converts a slice of handler arguments to Fiber handlers.
- // The context string is used to provide informative panic messages when an
- // unsupported handler type is encountered.
- func collectHandlers(context string, args ...any) []Handler {
- handlers := make([]Handler, 0, len(args))
- for i, arg := range args {
- handler, ok := toFiberHandler(arg)
- if !ok {
- panic(fmt.Sprintf("%s: invalid handler #%d (%T)\n", context, i, arg))
- }
- handlers = append(handlers, handler)
- }
- return handlers
- }
|