v2.0.0
⚠ Breaking Changes
- func(c *fiber.Ctx) error is the new Handler type accepting an error return, this will simplify error handling and create cleaner code because you can directly return outgoing methods like c.Send(), c.Next(), c.SendStatus(), c.Redirect() etc... #218
// func(c *fiber.Ctx) {}
func(c *fiber.Ctx) error {}
app.Use(func(c *fiber.Ctx) error {
if c.Get("x-john") == "doe" {
return c.Next()
}
return c.SendStatus(fiber.StatusForbidden)
})
app.Use("/teapot", func(c *fiber.Ctx) error {
return c.Send([]byte("Helllo, Teapot ☕!"))
})
app.Get("/world", func(c *fiber.Ctx) error {
return c.SendString("Hello, World 👋!")
})
app.Get("/redirect", func(c *fiber.Ctx) error {
return c.Redirect("https://google.com")
})
- fiber.New() takes an optional Config struct as value that will replace the *Settings pointer.
// func New(settings ...*Settings) *App {}
func New(config... Config) *App {}
- app.Listen() now contains a strong typed signature accepting an
string
addr argument.
To enable TLS, provide your own listener app.Listener(ln net.Listener) #555
// func (app *App) Listen(address interface{}, tlsconfig ...*tls.Config) error {}
func (app *App) Listen(addr string) error {}
- app.Listener() will remove the optional *tls.Config argument, this should be set within the given listener.
Prefork
will be compatible with custom listeners.
// func (app *App) Listener(ln net.Listener, tlsconfig ...*tls.Config) error {}
func (app *App) Listener(ln net.Listener) error {}
- c.Next() returns an error to be used with the new Ctx handler signature. Passing an error through c.Next is not necessary anymore since we return all errors within the handler.
// func (c *Ctx) Next(err ...error) {}
func (c *Ctx) Next() error {}
- c.Body() now returns []byte type instead of a string
// func (c *Ctx) Body() string {}
func (c *Ctx) Body() []byte {}
- c.Write() will comply with the io.Writer interface.
// func (c *Ctx) Write(bodies ...interface{}) {}
func (c *Ctx) Write(p []byte) (n int, err error) {}
- c.Context() returns the original
*fasthttp.RequestCtx
and is still compatible with thecontext.Context
interface.
// func (c *Ctx) Context() context.Context
func (c *Ctx) Context() *fasthttp.RequestCtx
- app.IsChild() will be available on the package layer
// func (app *App) IsChild() bool {}
func IsChild() bool {}
🧹 Updates
- c.Send() now contains a strong typed signature accepting a single []byte type
Other outgoing Send methods also return an error to comply with the new Handler signature
// func (c *Ctx) Send(bodies ...interface{}) {}
func (c *Ctx) Send(body []byte) error {}
// func (c *Ctx) SendStatus(status int) {}
func (c *Ctx) SendStatus(status int) error {}
// func (c *Ctx) SendString(body string) {}
func (c *Ctx) SendString(body string) error {}
// func (c *Ctx) SendStream(stream io.Reader, size ...int) {}
func (c *Ctx) SendStream(stream io.Reader, size ...int) error {}
- c.Redirect() now returns an error
// func (c *Ctx) Redirect(location string, status ...int) {}
func (c *Ctx) Redirect(location string, status ...int) error {}
- c.FormValue() now supports the optional
defaultValue
argument
// func (c *Ctx) FormValue(key string) string {}
func (c *Ctx) FormValue(key string, defaultValue ...string) string {}
⚠ Removed
- c.SendBytes() will be removed and is replaced by c.Send
// func (c *Ctx) SendBytes(body []byte) {}
- c.Error() will be removed because errors can be accessed using the error return in c.Next() error
// func (c *Ctx) Error() error {}
🔥 New
- c.Request() is a replacing method to access
*fasthttp.Request
.
// c.Fasthttp.Request.Header.Peek("x-version")
c.Request().Header.Peek("x-version")
- c.Response() is a replacing method to access
*fasthttp.Response
.
// c.Fasthttp.Response.Header.Peek("x-version")
c.Response().Header.Peek("x-version")
- app.Config.ErrorHandler will replace the app.Settings.ErrorHandler to override the default error handler.
app := fiber.New(fiber.Config{
ErrorHandler: func(c *fiber.Ctx, err error) error {
return c.Status(404).SendString("hi, i'm an custom error")
},
})
app.Get("/", func(c *fiber.Ctx) error {
return c.SendFile("../there/is/nothing/here")
})
- Config.ProxyHeader will enable
c.IP()
to return the value of the given header key. By defaultc.IP()
will return the Remote IP from the tcp connection, this property can be useful if you are behind a load balancer e.g. X-Forwarded-*.
app := fiber.New(fiber.Config{
ProxyHeader: "CF-Connecting-IP",
})
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString(c.IP()) // value from CF-Connecting-IP header
})
- Config.GETOnly rejects all non-GET requests if set to true. This option is useful as anti-DoS protection for servers accepting only GET requests and will return an
ErrMethodNotAllowed
to the error handler. The request size is limited by ReadBufferSize if GETOnly is set. Server accepts all the requests by default.
app := fiber.New(fiber.Config{
GETOnly: true,
})
app.Post("/", func(c *fiber.Ctx) error {
return c.SendString("This method is not allowed")
})
🚀 Routing
- The logic for parsing the route now better recognizes the parts which are not parameters, so the parameter can be placed anywhere, it is only important that the normal non-optional parameters are terminated by a delimiter character:
// Route
app.Get("/test::param/", handler)
// GET /test:fiber/
// Route
app.Get("/shop/product/color::color/size::size", handler)
// GET /shop/product/color:blue/size:xs
// Route
app.Get("/@:name", handler)
// GET /@Fiber
- Added support for the plus parameter, this is greedy like the wildcard parameter with the difference that it is required:
// Route
app.Get("/config/+.json", func(c *fiber.Ctx) error {
ctx.Params("+1") // abc
ctx.Params("+") // abc
})
// GET /config/abc.json // match
// GET /config/.json // no match
- Support for multiple wildcard and plus parameters has been added, they can now be accessed via wildcard or plus character with the counter in the route or normally for the first as in the current fiber version:
// GET /customer/v1/cart/proxy
app.Get("/*v1*/proxy", func(c *fiber.Ctx) error {
c.Params("*") // customer/
c.Params("*1") // customer/
c.Params("*2") // /cart
})
📦 Middleware
- github.com/gofiber/fiber/v2/middleware/basicauth
- github.com/gofiber/fiber/v2/middleware/compress
- github.com/gofiber/fiber/v2/middleware/cors
- github.com/gofiber/fiber/v2/middleware/csrf
- github.com/gofiber/fiber/v2/middleware/favicon
- github.com/gofiber/fiber/v2/middleware/filesystem
- github.com/gofiber/fiber/v2/middleware/limiter
- github.com/gofiber/fiber/v2/middleware/logger
- github.com/gofiber/fiber/v2/middleware/pprof
- github.com/gofiber/fiber/v2/middleware/proxy
- github.com/gofiber/fiber/v2/middleware/recover
- github.com/gofiber/fiber/v2/middleware/requestid
- github.com/gofiber/fiber/v2/middleware/timeout
🚀 Improvements
- The new version will use the segmentio/encoding package to encode JSON, this will improve performance drastically.
// v1.14.x
Benchmark_Ctx_JSON-16 4596667 260 ns/op 64 B/op 2 allocs/op
Benchmark_Ctx_JSON-16 4603731 259 ns/op 64 B/op 2 allocs/op
Benchmark_Ctx_JSON-16 4652700 259 ns/op 64 B/op 2 allocs/op
Benchmark_Ctx_JSON-16 4598620 259 ns/op 64 B/op 2 allocs/op
// v2.0.0
Benchmark_Ctx_JSON-16 7186842 165 ns/op 64 B/op 2 allocs/op
Benchmark_Ctx_JSON-16 7214056 164 ns/op 64 B/op 2 allocs/op
Benchmark_Ctx_JSON-16 7227295 164 ns/op 64 B/op 2 allocs/op
Benchmark_Ctx_JSON-16 7227291 165 ns/op 64 B/op 2 allocs/op
405 Method Not Allowed
will be passed to the global error handler, in the old version this behavior was not controllable.- This version will ship with fasthttp v1.16.0 which contains the statusLine/statusMessage PR found by @ReneWerner87, @Fenny and @kiyonlin
v2.0.0
allows us to implement a hybrid radix tree router which will remove the remaining allocation whenCaseSenstitive
is disabled and increase performance drasticly. The reason why we went with the hybrid implementation is because we still want to respect the router stack order 😉 thnx @ReneWerner87
// v1.14.x
Benchmark_Router_NotFound-16 235243 4843 ns/op 80 B/op 2 allocs/op
Benchmark_Router_Handler-16 1721277 696 ns/op 16 B/op 1 allocs/op
Benchmark_Router_Handler_Strict_Case-16 1848582 651 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Chain-16 9300248 129 ns/op 1 B/op 1 allocs/op
Benchmark_Router_WithCompression-16 8693692 137 ns/op 1 B/op 1 allocs/op
Benchmark_Router_Next-16 1960342 619 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Handler_CaseSensitive-16 1862936 649 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Handler_Unescape-16 255260 4573 ns/op 16 B/op 1 allocs/op
Benchmark_Router_Handler_StrictRouting-16 1857168 647 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Github_API-16 3634 317628 ns/op 0 B/op 0 allocs/op
// v2.0.0
Benchmark_Router_NotFound-16 2919049 411 ns/op 48 B/op 1 allocs/op
Benchmark_Router_Handler-16 8331446 145 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Handler_Strict_Case-16 9675211 124 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Chain-16 9088828 132 ns/op 0 B/op 0 allocs/op
Benchmark_Router_WithCompression-16 9020534 133 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Next-16 14454469 81 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Handler_CaseSensitive-16 9597826 124 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Handler_Unescape-16 6059216 196 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Handler_StrictRouting-16 9753892 123 ns/op 0 B/op 0 allocs/op
Benchmark_Router_Github_API-16 5452 214098 ns/op 0 B/op 0 allocs/op
See: ( 🚀 v2 benchmark results )