π App
Helpersβ
GetStringβ
Returns s unchanged when Immutable is disabled or s resides in read-only memory. Otherwise, it returns a detached copy using strings.Clone.
func (app *App) GetString(s string) string
GetBytesβ
Returns b unchanged when Immutable is disabled or b resides in read-only memory. Otherwise, it returns a detached copy.
func (app *App) GetBytes(b []byte) []byte
Routingβ
Route Handlersβ
Registers a route bound to a specific HTTP method.
// HTTP methods
func (app *App) Get(path string, handler any, handlers ...any) Router
func (app *App) Head(path string, handler any, handlers ...any) Router
func (app *App) Post(path string, handler any, handlers ...any) Router
func (app *App) Put(path string, handler any, handlers ...any) Router
func (app *App) Delete(path string, handler any, handlers ...any) Router
func (app *App) Connect(path string, handler any, handlers ...any) Router
func (app *App) Options(path string, handler any, handlers ...any) Router
func (app *App) Trace(path string, handler any, handlers ...any) Router
func (app *App) Patch(path string, handler any, handlers ...any) Router
// Add allows you to specify multiple methods at once
func (app *App) Add(methods []string, path string, handler any, handlers ...any) Router
// All will register the route on all HTTP methods
// Almost the same as app.Use but not bound to prefixes
func (app *App) All(path string, handler any, handlers ...any) Router
Fiber's adapter converts a variety of handler shapes to native
func(fiber.Ctx) error callbacks. It currently recognizes thirteen cases (the
numbers below match the comments in toFiberHandler inside adapter.go). This
lets you mix Fiber-style handlers with Express-style callbacks and even reuse
net/http or fasthttp functions.
Fiber-native handlers (cases 1β2)β
- Case 1.
fiber.Handlerβ the canonicalfunc(fiber.Ctx) errorform. - Case 2.
func(fiber.Ctx)β Fiber runs the function and treats it as if it returnednil.
Express-style request handlers (cases 3β8)β
- Case 3.
func(fiber.Req, fiber.Res) error - Case 4.
func(fiber.Req, fiber.Res) - Case 5.
func(fiber.Req, fiber.Res, func() error) error - Case 6.
func(fiber.Req, fiber.Res, func() error) - Case 7.
func(fiber.Req, fiber.Res, func()) error - Case 8.
func(fiber.Req, fiber.Res, func())
The adapter injects a next callback when your signature accepts one. Fiber
propagates downstream errors from c.Next() back through the wrapper, so
returning those errors remains optional. If you never call the injected next
function, the handler chain stops, matching Express semantics.
net/http handlers (cases 9β11)β
- Case 9.
http.HandlerFunc - Case 10.
http.Handler - Case 11.
func(http.ResponseWriter, *http.Request)
Fiber adapts these handlers through fasthttpadaptor. They do not receive
fiber.Ctx, cannot call c.Next(), and therefore always terminate the handler
chain. The compatibility layer also adds more overhead than running a native
Fiber handler, so prefer the other forms when possible.
fasthttp handlers (cases 12β13)β
- Case 12.
fasthttp.RequestHandler - Case 13.
func(*fasthttp.RequestCtx) error
fasthttp handlers run with full access to the underlying fasthttp.RequestCtx.
They are expected to manage the response directly. Fiber will propagate any
error returned by the func(*fasthttp.RequestCtx) error variant but otherwise
does not inspect the context state.
// Simple GET handler (Fiber accepts both func(fiber.Ctx) and func(fiber.Ctx) error)
app.Get("/api/list", func(c fiber.Ctx) error {
return c.SendString("I'm a GET request!")
})
// Reuse an existing net/http handler without manual adaptation
httpHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusNoContent)
})
app.Get("/foo", httpHandler)
// Align with Express-style handlers using fiber.Req and fiber.Res helpers (works
// for middleware and routes alike)
app.Use(func(req fiber.Req, res fiber.Res, next func() error) error {
if req.IP() == "192.168.1.254" {
return res.SendStatus(fiber.StatusForbidden)
}
return next()
})
app.Get("/express", func(req fiber.Req, res fiber.Res) error {
return res.SendString("Hello from Express-style handlers!")
})
// Mount a fasthttp.RequestHandler directly
app.Get("/bar", func(ctx *fasthttp.RequestCtx) {
ctx.SetStatusCode(fiber.StatusAccepted)
})
// Simple POST handler
app.Post("/api/register", func(c fiber.Ctx) error {
return c.SendString("I'm a POST request!")
})
Can be used for middleware packages and prefix catchers. Prefixes now require either an exact match or a slash boundary, so /john matches /john and /john/doe but not /johnnnnn. Parameter tokens like :name, :name?, *, and + are still expanded before the boundary check runs.
func (app *App) Use(args ...any) Router
// Fiber inspects args to support these common usage patterns:
// - app.Use(handler, handlers ...any)
// - app.Use(path string, handler, handlers ...any)
// - app.Use(paths []string, handler, handlers ...any)
// - app.Use(path string, subApp *App)
Each handler argument can independently be a Fiber handler (with or without an
error return), an Express-style callback, a net/http handler, or any other
supported shape including fasthttp callbacks that return errors.
// Match any request
app.Use(func(c fiber.Ctx) error {
return c.Next()
})
// Match request starting with /api
app.Use("/api", func(c fiber.Ctx) error {
return c.Next()
})
// Match requests starting with /api or /home (multiple-prefix support)
app.Use([]string{"/api", "/home"}, func(c fiber.Ctx) error {
return c.Next()
})
// Attach multiple handlers
app.Use("/api", func(c fiber.Ctx) error {
c.Set("X-Custom-Header", random.String(32))
return c.Next()
}, func(c fiber.Ctx) error {
return c.Next()
})
// Mount a sub-app
app.Use("/api", api)
Mountingβ
Mount another Fiber instance with app.Use, similar to Express's router.use.
package main
import (
"log"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
micro := fiber.New()
// Mount the micro app on the "/john" route
app.Use("/john", micro) // GET /john/doe -> 200 OK
micro.Get("/doe", func(c fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})
log.Fatal(app.Listen(":3000"))
}
MountPathβ
The MountPath property contains one or more path patterns on which a sub-app was mounted.
func (app *App) MountPath() string
package main
import (
"fmt"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
one := fiber.New()
two := fiber.New()
three := fiber.New()
two.Use("/three", three)
one.Use("/two", two)
app.Use("/one", one)
fmt.Println("Mount paths:")
fmt.Println("one.MountPath():", one.MountPath()) // "/one"
fmt.Println("two.MountPath():", two.MountPath()) // "/one/two"
fmt.Println("three.MountPath():", three.MountPath()) // "/one/two/three"
fmt.Println("app.MountPath():", app.MountPath()) // ""
}
Mounting order is important for MountPath. To get mount paths properly, you should start mounting from the deepest app.
Groupβ
You can group routes by creating a *Group struct.
func (app *App) Group(prefix string, handlers ...any) Router
package main
import (
"log"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
api := app.Group("/api", handler) // /api
v1 := api.Group("/v1", handler) // /api/v1
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user
v2 := api.Group("/v2", handler) // /api/v2
v2.Get("/list", handler) // /api/v2/list
v2.Get("/user", handler) // /api/v2/user
log.Fatal(app.Listen(":3000"))
}
func handler(c fiber.Ctx) error {
return c.SendString("Handler response")
}
RouteChainβ
Returns an instance of a single route, which you can then use to handle HTTP verbs with optional middleware.
Similar to Express.
func (app *App) RouteChain(path string) Register
Click here to see the Register interface
type Register interface {
All(handler any, handlers ...any) Register
Get(handler any, handlers ...any) Register
Head(handler any, handlers ...any) Register
Post(handler any, handlers ...any) Register
Put(handler any, handlers ...any) Register
Delete(handler any, handlers ...any) Register
Connect(handler any, handlers ...any) Register
Options(handler any, handlers ...any) Register
Trace(handler any, handlers ...any) Register
Patch(handler any, handlers ...any) Register
Add(methods []string, handler any, handlers ...any) Register
RouteChain(path string) Register
}
package main
import (
"log"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
// Use `RouteChain` as a chainable route declaration method
app.RouteChain("/test").Get(func(c fiber.Ctx) error {
return c.SendString("GET /test")
})
app.RouteChain("/events").All(func(c fiber.Ctx) error {
// Runs for all HTTP verbs first
// Think of it as route-specific middleware!
}).
Get(func(c fiber.Ctx) error {
return c.SendString("GET /events")
}).
Post(func(c fiber.Ctx) error {
// Maybe add a new event...
return c.SendString("POST /events")
})
// Combine multiple routes
app.RouteChain("/reports").RouteChain("/daily").Get(func(c fiber.Ctx) error {
return c.SendString("GET /reports/daily")
})
// Use multiple methods
app.RouteChain("/api").Get(func(c fiber.Ctx) error {
return c.SendString("GET /api")
}).Post(func(c fiber.Ctx) error {
return c.SendString("POST /api")
})
log.Fatal(app.Listen(":3000"))
}
Routeβ
Defines routes with a common prefix inside the supplied function. Internally it uses Group to create a sub-router and accepts an optional name prefix.
func (app *App) Route(prefix string, fn func(router Router), name ...string) Router
app.Route("/test", func(api fiber.Router) {
api.Get("/foo", handler).Name("foo") // /test/foo (name: test.foo)
api.Get("/bar", handler).Name("bar") // /test/bar (name: test.bar)
}, "test.")
HandlersCountβ
Returns the number of registered handlers.
func (app *App) HandlersCount() uint32
Stackβ
Returns the underlying router stack.
func (app *App) Stack() [][]*Route
package main
import (
"encoding/json"
"log"
"github.com/gofiber/fiber/v3"
)
var handler = func(c fiber.Ctx) error { return nil }
func main() {
app := fiber.New()
app.Get("/john/:age", handler)
app.Post("/register", handler)
data, _ := json.MarshalIndent(app.Stack(), "", " ")
fmt.Println(string(data))
log.Fatal(app.Listen(":3000"))
}
Click here to see the result
[
[
{
"method": "GET",
"path": "/john/:age",
"params": [
"age"
]
}
],
[
{
"method": "HEAD",
"path": "/john/:age",
"params": [
"age"
]
}
],
[
{
"method": "POST",
"path": "/register",
"params": null
}
]
]
Nameβ
This method assigns the name to the latest created route.
func (app *App) Name(name string) Router
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/gofiber/fiber/v3"
)
func main() {
var handler = func(c fiber.Ctx) error { return nil }
app := fiber.New()
app.Get("/", handler)
app.Name("index")
app.Get("/doe", handler).Name("home")
app.Trace("/tracer", handler).Name("tracert")
app.Delete("/delete", handler).Name("delete")
a := app.Group("/a")
a.Name("fd.")
a.Get("/test", handler).Name("test")
data, _ := json.MarshalIndent(app.Stack(), "", " ")
fmt.Println(string(data))
log.Fatal(app.Listen(":3000"))
}
Click here to see the result
[
[
{
"method": "GET",
"name": "index",
"path": "/",
"params": null
},
{
"method": "GET",
"name": "home",
"path": "/doe",
"params": null
},
{
"method": "GET",
"name": "fd.test",
"path": "/a/test",
"params": null
}
],
[
{
"method": "HEAD",
"name": "",
"path": "/",
"params": null
},
{
"method": "HEAD",
"name": "",
"path": "/doe",
"params": null
},
{
"method": "HEAD",
"name": "",
"path": "/a/test",
"params": null
}
],
null,
null,
[
{
"method": "DELETE",
"name": "delete",
"path": "/delete",
"params": null
}
],
null,
null,
[
{
"method": "TRACE",
"name": "tracert",
"path": "/tracer",
"params": null
}
],
null
]
GetRouteβ
This method retrieves a route by its name.
func (app *App) GetRoute(name string) Route
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
app.Get("/", handler).Name("index")
route := app.GetRoute("index")
data, _ := json.MarshalIndent(route, "", " ")
fmt.Println(string(data))
log.Fatal(app.Listen(":3000"))
}
Click here to see the result
{
"method": "GET",
"name": "index",
"path": "/",
"params": null
}
GetRoutesβ
This method retrieves all routes.
func (app *App) GetRoutes(filterUseOption ...bool) []Route
When filterUseOption is set to true, it filters out routes registered by middleware.
package main
import (
"encoding/json"
"fmt"
"log"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
app.Post("/", func(c fiber.Ctx) error {
return c.SendString("Hello, World!")
}).Name("index")
routes := app.GetRoutes(true)
data, _ := json.MarshalIndent(routes, "", " ")
fmt.Println(string(data))
log.Fatal(app.Listen(":3000"))
}
Click here to see the result
[
{
"method": "POST",
"name": "index",
"path": "/",
"params": null
}
]
Configβ
Config returns the app config as a value (read-only).
func (app *App) Config() Config
Handlerβ
Handler returns the server handler that can be used to serve custom \*fasthttp.RequestCtx requests.
func (app *App) Handler() fasthttp.RequestHandler
ErrorHandlerβ
ErrorHandler executes the process defined for the application in case of errors. This is used in some cases in middlewares.
func (app *App) ErrorHandler(ctx Ctx, err error) error
NewWithCustomCtxβ
NewWithCustomCtx creates a new *App and sets the custom context factory
function at construction time.
func NewWithCustomCtx(fn func(app *App) CustomCtx, config ...Config) *App
package main
import (
"log"
"github.com/gofiber/fiber/v3"
)
type CustomCtx struct {
fiber.DefaultCtx
}
func (c *CustomCtx) Params(key string, defaultValue ...string) string {
return "prefix_" + c.DefaultCtx.Params(key)
}
func main() {
app := fiber.NewWithCustomCtx(func(app *fiber.App) fiber.CustomCtx {
return &CustomCtx{
DefaultCtx: *fiber.NewDefaultCtx(app),
}
})
app.Get("/:id", func(c fiber.Ctx) error {
return c.SendString(c.Params("id"))
})
log.Fatal(app.Listen(":3000"))
}
RegisterCustomBinderβ
You can register custom binders to use with Bind().Custom("name"). They should be compatible with the CustomBinder interface.
func (app *App) RegisterCustomBinder(binder CustomBinder)
package main
import (
"log"
"github.com/gofiber/fiber/v3"
"gopkg.in/yaml.v2"
)
type User struct {
Name string `yaml:"name"`
}
type customBinder struct{}
func (*customBinder) Name() string {
return "custom"
}
func (*customBinder) MIMETypes() []string {
return []string{"application/yaml"}
}
func (*customBinder) Parse(c fiber.Ctx, out any) error {
// Parse YAML body
return yaml.Unmarshal(c.Body(), out)
}
func main() {
app := fiber.New()
// Register custom binder
app.RegisterCustomBinder(&customBinder{})
app.Post("/custom", func(c fiber.Ctx) error {
var user User
// Use Custom binder by name
if err := c.Bind().Custom("custom", &user); err != nil {
return err
}
return c.JSON(user)
})
app.Post("/normal", func(c fiber.Ctx) error {
var user User
// Custom binder is used by the MIME type
if err := c.Bind().Body(&user); err != nil {
return err
}
return c.JSON(user)
})
log.Fatal(app.Listen(":3000"))
}
RegisterCustomConstraintβ
RegisterCustomConstraint allows you to register custom constraints.
func (app *App) RegisterCustomConstraint(constraint CustomConstraint)
See the Custom Constraint section for more information.
SetTLSHandlerβ
Use SetTLSHandler to set ClientHelloInfo when using TLS with a Listener.
func (app *App) SetTLSHandler(tlsHandler *TLSHandler)
Testβ
Testing your application is done with the Test method. Use this method for creating _test.go files or when you need to debug your routing logic. The default timeout is 1s; to disable a timeout altogether, pass a TestConfig struct with Timeout: 0.
func (app *App) Test(req *http.Request, config ...TestConfig) (*http.Response, error)
package main
import (
"fmt"
"io"
"log"
"net/http"
"net/http/httptest"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
// Create route with GET method for test:
app.Get("/", func(c fiber.Ctx) error {
fmt.Println(c.BaseURL()) // => http://google.com
fmt.Println(c.Get("X-Custom-Header")) // => hi
return c.SendString("hello, World!")
})
// Create http.Request
req := httptest.NewRequest("GET", "http://google.com", nil)
req.Header.Set("X-Custom-Header", "hi")
// Perform the test
resp, _ := app.Test(req)
// Do something with the results:
if resp.StatusCode == fiber.StatusOK {
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body)) // => hello, World!
}
}
If not provided, TestConfig is set to the following defaults:
config := fiber.TestConfig{
Timeout: time.Second(),
FailOnTimeout: true,
}
This is not the same as supplying an empty TestConfig{} to
`app.Test(), but rather be the equivalent of supplying:
cfg := fiber.TestConfig{
Timeout: 0,
FailOnTimeout: false,
}
This would make a Test that has no timeout.
Hooksβ
Hooks is a method to return the hooks property.
func (app *App) Hooks() *Hooks
RebuildTreeβ
The RebuildTree method is designed to rebuild the route tree and enable dynamic route registration. It returns a pointer to the App instance.
func (app *App) RebuildTree() *App
Note: Use this method with caution. It is not thread-safe and calling it can be very performance-intensive, so it should be used sparingly and only in development mode. Avoid using it concurrently.
Example Usageβ
Hereβs an example of how to define and register routes dynamically:
package main
import (
"log"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
app.Get("/define", func(c fiber.Ctx) error {
// Define a new route dynamically
app.Get("/dynamically-defined", func(c fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
})
// Rebuild the route tree to register the new route
app.RebuildTree()
return c.SendStatus(fiber.StatusOK)
})
log.Fatal(app.Listen(":3000"))
}
In this example, a new route is defined and then RebuildTree() is called to ensure the new route is registered and available.
RemoveRouteβ
This method removes a route by path. You must call the RebuildTree() method after the removal to finalize the update and rebuild the routing tree.
If no methods are specified, the route will be removed for all HTTP methods defined in the app. To limit removal to specific methods, provide them as additional arguments.
func (app *App) RemoveRoute(path string, methods ...string)
package main
import (
"log"
"github.com/gofiber/fiber/v3"
)
func main() {
app := fiber.New()
app.Get("/api/feature-a", func(c fiber.Ctx) error {
app.RemoveRoute("/api/feature", fiber.MethodGet)
app.RebuildTree()
// Redefine route
app.Get("/api/feature", func(c fiber.Ctx) error {
return c.SendString("Testing feature-a")
})
app.RebuildTree()
return c.SendStatus(fiber.StatusOK)
})
app.Get("/api/feature-b", func(c fiber.Ctx) error {
app.RemoveRoute("/api/feature", fiber.MethodGet)
app.RebuildTree()
// Redefine route
app.Get("/api/feature", func(c fiber.Ctx) error {
return c.SendString("Testing feature-b")
})
app.RebuildTree()
return c.SendStatus(fiber.StatusOK)
})
log.Fatal(app.Listen(":3000"))
}
RemoveRouteByNameβ
This method removes a route by name. If no methods are specified, the route will be removed for all HTTP methods defined in the app. To limit removal to specific methods, provide them as additional arguments.
func (app *App) RemoveRouteByName(name string, methods ...string)
RemoveRouteFuncβ
This method removes a route by function having *Route parameter.
If no methods are specified, the route will be removed for all HTTP methods defined in the app. To limit removal to specific methods, provide them as additional arguments.
func (app *App) RemoveRouteFunc(matchFunc func(r *Route) bool, methods ...string)