github gofiber/fiber v2.0.0

latest releases: v3.0.0-beta.3, v2.52.5, v3.0.0-beta.2...
4 years ago

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) {}
// 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.Fasthttp.Request.Header.Peek("x-version")
   c.Request().Header.Peek("x-version")
// 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 default c.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

🚀 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 when CaseSenstitive 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 )

Don't miss a new fiber release

NewReleases is sending notifications on new releases.