diff --git a/app.go b/app.go index 148b2f35..c686fb5f 100644 --- a/app.go +++ b/app.go @@ -35,9 +35,9 @@ import ( const Version = "3.0.0-beta.4" // Handler defines a function to serve HTTP requests. -type Handler = func(Ctx[any]) error +type Handler = func(ctx Ctx) error -type customCtxFunc = func(app *App[any]) CustomCtx[any] +type customCtxFunc = func(app *App[Ctx]) CustomCtx[Ctx] // Map is a shortcut for map[string]any, useful for JSON returns type Map map[string]any @@ -80,7 +80,7 @@ type Storage interface { // return c.Status(code).SendString(err.Error()) // } // app := fiber.New(cfg) -type ErrorHandler = func(Ctx[any], error) error +type ErrorHandler = func(Ctx, error) error // Error represents an error that occurred while handling a request. type Error struct { @@ -89,7 +89,7 @@ type Error struct { } // App denotes the Fiber application. -type App[TCtx any] struct { +type App[TCtx CtxGeneric[TCtx]] struct { // Ctx pool pool sync.Pool // Fasthttp server @@ -472,7 +472,7 @@ var DefaultMethods = []string{ } // DefaultErrorHandler that process return errors from handlers -func DefaultErrorHandler(c Ctx[any], err error) error { +func DefaultErrorHandler(c Ctx, err error) error { code := StatusInternalServerError var e *Error if errors.As(err, &e) { @@ -493,7 +493,7 @@ func DefaultErrorHandler(c Ctx[any], err error) error { // ServerHeader: "Fiber", // }) func New(config ...Config) *App[DefaultCtx] { - app := newApp[any](config...) + app := newApp[DefaultCtx](config...) // Init app app.init() @@ -519,7 +519,7 @@ func New(config ...Config) *App[DefaultCtx] { // Prefork: true, // ServerHeader: "Fiber", // }) -func NewWithCustomCtx[TCtx Ctx[TCtx]](newCtxFunc customCtxFunc, config ...Config) *App[TCtx] { +func NewWithCustomCtx[TCtx CtxGeneric[TCtx]](newCtxFunc customCtxFunc, config ...Config) *App[TCtx] { app := newApp[TCtx](config...) // Set newCtxFunc @@ -532,7 +532,7 @@ func NewWithCustomCtx[TCtx Ctx[TCtx]](newCtxFunc customCtxFunc, config ...Config } // newApp creates a new Fiber named instance. -func newApp[TCtx Ctx[TCtx]](config ...Config) *App[TCtx] { +func newApp[TCtx CtxGeneric[TCtx]](config ...Config) *App[TCtx] { // Create a new app app := &App[TCtx]{ // Create config @@ -1129,7 +1129,7 @@ func (app *App[TCtx]) init() *App[TCtx] { // sub fibers by their prefixes and if it finds a match, it uses that // error handler. Otherwise it uses the configured error handler for // the app, which if not set is the DefaultErrorHandler. -func (app *App[TCtx]) ErrorHandler(ctx Ctx[TCtx], err error) error { +func (app *App[TCtx]) ErrorHandler(ctx CtxGeneric[TCtx], err error) error { var ( mountedErrHandler ErrorHandler mountedPrefixParts int diff --git a/bind.go b/bind.go index eac6d5a5..13d9d367 100644 --- a/bind.go +++ b/bind.go @@ -9,7 +9,7 @@ import ( type CustomBinder interface { Name() string MIMETypes() []string - Parse(c Ctx[any], out any) error + Parse(c Ctx, out any) error } // StructValidator is an interface to register custom struct validator for binding. @@ -19,7 +19,7 @@ type StructValidator interface { // Bind struct type Bind struct { - ctx Ctx[any] + ctx Ctx dontHandleErrs bool } diff --git a/ctx.go b/ctx.go index c9c0c340..952c3995 100644 --- a/ctx.go +++ b/ctx.go @@ -47,10 +47,10 @@ const userContextKey contextKey = 0 // __local_user_context__ // generation tool `go install github.com/vburenin/ifacemaker@975a95966976eeb2d4365a7fb236e274c54da64c` // https://github.com/vburenin/ifacemaker/blob/975a95966976eeb2d4365a7fb236e274c54da64c/ifacemaker.go#L14-L30 // -//go:generate ifacemaker --file ctx.go --struct DefaultCtx --iface Ctx --pkg fiber --output ctx_interface.go --not-exported true --iface-comment "Ctx represents the Context which hold the HTTP request and response.\nIt has methods for the request query string, parameters, body, HTTP headers and so on." +//go:generate ifacemaker --file ctx.go --struct DefaultCtx --iface CtxGeneric --pkg fiber --output ctx_interface.go --not-exported true --iface-comment "Ctx represents the Context which hold the HTTP request and response.\nIt has methods for the request query string, parameters, body, HTTP headers and so on." //go:generate go run ctx_interface_gen.go type DefaultCtx struct { - app *App[any] // Reference to *App + app *App[*DefaultCtx] // Reference to *App route *Route // Reference to *Route fasthttp *fasthttp.RequestCtx // Reference to *fasthttp.RequestCtx bind *Bind // Default bind reference @@ -72,6 +72,8 @@ type DefaultCtx struct { matched bool // Non use route matched } +type Ctx = CtxGeneric[*DefaultCtx] + // SendFile defines configuration options when to transfer file with SendFile. type SendFile struct { // FS is the file system to serve the static files from. @@ -198,7 +200,7 @@ type Views interface { // ResFmt associates a Content Type to a fiber.Handler for c.Format type ResFmt struct { - Handler func(Ctx[any]) error + Handler func(Ctx) error MediaType string } @@ -223,7 +225,7 @@ func (c *DefaultCtx) AcceptsLanguages(offers ...string) string { } // App returns the *App reference to the instance of the Fiber application -func (c *DefaultCtx) App() *App[DefaultCtx] { +func (c *DefaultCtx) App() *App[*DefaultCtx] { return c.app } @@ -643,7 +645,7 @@ func (c *DefaultCtx) Get(key string, defaultValue ...string) string { // GetReqHeader returns the HTTP request header specified by filed. // This function is generic and can handle different headers type values. -func GetReqHeader[V GenericType](c Ctx[any], key string, defaultValue ...V) V { +func GetReqHeader[V GenericType](c Ctx, key string, defaultValue ...V) V { var v V return genericParseType[V](c.App().getString(c.Request().Header.Peek(key)), v, defaultValue...) } @@ -979,7 +981,7 @@ func (c *DefaultCtx) Locals(key any, value ...any) any { // All the values are removed from ctx after returning from the top // RequestHandler. Additionally, Close method is called on each value // implementing io.Closer before removing the value from ctx. -func Locals[V any](c Ctx[any], key any, value ...V) V { +func Locals[V any](c Ctx, key any, value ...V) V { var v V var ok bool if len(value) == 0 { @@ -1115,7 +1117,7 @@ func (c *DefaultCtx) Params(key string, defaultValue ...string) string { // // http://example.com/id/:number -> http://example.com/id/john // Params[int](c, "number", 0) -> returns 0 because can't parse 'john' as integer. -func Params[V GenericType](c Ctx[any], key string, defaultValue ...V) V { +func Params[V GenericType](c Ctx, key string, defaultValue ...V) V { var v V return genericParseType(c.Params(key), v, defaultValue...) } @@ -1237,7 +1239,7 @@ func (c *DefaultCtx) Queries() map[string]string { // name := Query[string](c, "search") // Returns "john" // age := Query[int](c, "age") // Returns 8 // unknown := Query[string](c, "unknown", "default") // Returns "default" since the query parameter "unknown" is not found -func Query[V GenericType](c Ctx[any], key string, defaultValue ...V) V { +func Query[V GenericType](c Ctx, key string, defaultValue ...V) V { var v V q := c.App().getString(c.RequestCtx().QueryArgs().Peek(key)) @@ -1731,7 +1733,7 @@ func (c *DefaultCtx) Stale() bool { // Status sets the HTTP status for the response. // This method is chainable. -func (c *DefaultCtx) Status(status int) Ctx[DefaultCtx] { +func (c *DefaultCtx) Status(status int) *DefaultCtx { c.fasthttp.Response.SetStatusCode(status) return c } @@ -1776,7 +1778,7 @@ func (c *DefaultCtx) String() string { } // Type sets the Content-Type HTTP header to the MIME type specified by the file extension. -func (c *DefaultCtx) Type(extension string, charset ...string) Ctx[DefaultCtx] { +func (c *DefaultCtx) Type(extension string, charset ...string) *DefaultCtx { if len(charset) > 0 { c.fasthttp.Response.Header.SetContentType(utils.GetMIME(extension) + "; charset=" + charset[0]) } else { diff --git a/ctx_custom_interface.go b/ctx_custom_interface.go index 73a5a57e..263292b3 100644 --- a/ctx_custom_interface.go +++ b/ctx_custom_interface.go @@ -11,7 +11,7 @@ import ( ) type CustomCtx[T any] interface { - Ctx[T] + CtxGeneric[T] // Reset is a method to reset context fields by given request when to use server handlers. Reset(fctx *fasthttp.RequestCtx) @@ -30,7 +30,7 @@ type CustomCtx[T any] interface { setRoute(route *Route) } -func NewDefaultCtx(app *App[DefaultCtx]) *DefaultCtx { +func NewDefaultCtx(app *App[*DefaultCtx]) *DefaultCtx { // return ctx return &DefaultCtx{ // Set app reference @@ -38,8 +38,8 @@ func NewDefaultCtx(app *App[DefaultCtx]) *DefaultCtx { } } -func (app *App[TCtx]) newCtx() Ctx[TCtx] { - var c Ctx[TCtx] +func (app *App[TCtx]) newCtx() CtxGeneric[TCtx] { + var c CtxGeneric[TCtx] if app.newCtxFunc != nil { c = app.newCtxFunc(app) @@ -51,8 +51,8 @@ func (app *App[TCtx]) newCtx() Ctx[TCtx] { } // AcquireCtx retrieves a new Ctx from the pool. -func (app *App[TCtx]) AcquireCtx(fctx *fasthttp.RequestCtx) Ctx[TCtx] { - ctx, ok := app.pool.Get().(Ctx) +func (app *App[TCtx]) AcquireCtx(fctx *fasthttp.RequestCtx) CtxGeneric[TCtx] { + ctx, ok := app.pool.Get().(CtxGeneric[TCtx]) if !ok { panic(errors.New("failed to type-assert to Ctx")) @@ -63,7 +63,7 @@ func (app *App[TCtx]) AcquireCtx(fctx *fasthttp.RequestCtx) Ctx[TCtx] { } // ReleaseCtx releases the ctx back into the pool. -func (app *App[TCtx]) ReleaseCtx(c Ctx[TCtx]) { +func (app *App[TCtx]) ReleaseCtx(c CtxGeneric[TCtx]) { c.release() app.pool.Put(c) } diff --git a/ctx_interface.go b/ctx_interface.go index 19f7e682..7f324289 100644 --- a/ctx_interface.go +++ b/ctx_interface.go @@ -12,9 +12,9 @@ import ( "github.com/valyala/fasthttp" ) -// T represents the Context which hold the HTTP request and response. +// Ctx represents the Context which hold the HTTP request and response. // It has methods for the request query string, parameters, body, HTTP headers and so on. -type Ctx[T any] interface { +type CtxGeneric[T any] interface { // Accepts checks if the specified extensions or content types are acceptable. Accepts(offers ...string) string // AcceptsCharsets checks if the specified charset is acceptable. diff --git a/ctx_interface_gen.go b/ctx_interface_gen.go index bc4317d4..986f23cc 100644 --- a/ctx_interface_gen.go +++ b/ctx_interface_gen.go @@ -40,8 +40,8 @@ func patchCtxFile(input []byte) ([]byte, error) { scanner := bufio.NewScanner(in) var outBuf bytes.Buffer - regexCtx := regexp.MustCompile(`\bCtx\b`) - regexApp := regexp.MustCompile(`\*\bApp\b`) + regexCtx := regexp.MustCompile(`(\*Default)Ctx`) + regexApp := regexp.MustCompile(`\*App(\[\w+])?`) for scanner.Scan() { line := scanner.Text() @@ -50,8 +50,8 @@ func patchCtxFile(input []byte) ([]byte, error) { // => "type Ctx interface {" -> "type Ctx[T any] interface {" if strings.HasPrefix(line, "type") { line = strings.Replace(line, - "type Ctx interface {", - "type Ctx[T any] interface {", + "type CtxGeneric interface {", + "type CtxGeneric[T any] interface {", 1, ) } else { @@ -64,7 +64,6 @@ func patchCtxFile(input []byte) ([]byte, error) { // C) App with generic type if strings.Contains(line, "App") { - // TODO: check this part line = regexApp.ReplaceAllString(line, "*App[T]") } } diff --git a/group.go b/group.go index 04165ecb..fdf5118e 100644 --- a/group.go +++ b/group.go @@ -11,7 +11,7 @@ import ( // Group struct type Group struct { - app *App[any] + app *App[Ctx] parentGroup *Group name string diff --git a/hooks.go b/hooks.go index b6be6caa..b7c974f1 100644 --- a/hooks.go +++ b/hooks.go @@ -13,13 +13,13 @@ type ( OnListenHandler = func(ListenData) error OnShutdownHandler = func() error OnForkHandler = func(int) error - OnMountHandler = func(*App[any]) error + OnMountHandler = func(*App[Ctx]) error ) // Hooks is a struct to use it with App. type Hooks struct { // Embed app - app *App[any] + app *App[Ctx] // Hooks onRoute []OnRouteHandler @@ -39,7 +39,7 @@ type ListenData struct { TLS bool } -func newHooks(app *App[Ctx[any]]) *Hooks { +func newHooks(app *App[Ctx]) *Hooks { return &Hooks{ app: app, onRoute: make([]OnRouteHandler, 0), @@ -207,7 +207,7 @@ func (h *Hooks) executeOnForkHooks(pid int) { } } -func (h *Hooks) executeOnMountHooks(app *App[Ctx[any]]) error { +func (h *Hooks) executeOnMountHooks(app *App[Ctx]) error { for _, v := range h.onMount { if err := v(app); err != nil { return err diff --git a/mount.go b/mount.go index 282f9f87..8d32235c 100644 --- a/mount.go +++ b/mount.go @@ -15,7 +15,7 @@ import ( // Put fields related to mounting. type mountFields struct { // Mounted and main apps - appList map[string]*App[any] + appList map[string]*App[Ctx] // Prefix of app if it was mounted mountPath string // Ordered keys of apps (sorted by key length for Render) @@ -68,7 +68,7 @@ func (app *App[TCtx]) mount(prefix string, subApp *App[TCtx]) Router { // Mount attaches another app instance as a sub-router along a routing path. // It's very useful to split up a large API as many independent routers and // compose them as a single service using Mount. -func (grp *Group) mount(prefix string, subApp *App[Ctx[any]]) Router { +func (grp *Group) mount(prefix string, subApp *App[Ctx]) Router { groupPath := getGroupPath(grp.Prefix, prefix) groupPath = utils.TrimRight(groupPath, '/') if groupPath == "" {