1
0
Fork 0

Adding upstream version 2.52.6.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-05-17 06:50:16 +02:00
parent a960158181
commit 6d002e9543
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
441 changed files with 95392 additions and 0 deletions

8
docs/api/_category_.json Normal file
View file

@ -0,0 +1,8 @@
{
"label": "API",
"position": 2,
"link": {
"type": "generated-index",
"description": "API documentation for Fiber."
}
}

657
docs/api/app.md Normal file
View file

@ -0,0 +1,657 @@
---
id: app
title: 🚀 App
description: The app instance conventionally denotes the Fiber application.
sidebar_position: 2
---
import RoutingHandler from './../partials/routing/handler.md';
## Static
Use the **Static** method to serve static files such as **images**, **CSS,** and **JavaScript**.
:::info
By default, **Static** will serve `index.html` files in response to a request on a directory.
:::
```go title="Signature"
func (app *App) Static(prefix, root string, config ...Static) Router
```
Use the following code to serve files in a directory named `./public`
```go
app.Static("/", "./public")
// => http://localhost:3000/hello.html
// => http://localhost:3000/js/jquery.js
// => http://localhost:3000/css/style.css
```
```go title="Examples"
// Serve files from multiple directories
app.Static("/", "./public")
// Serve files from "./files" directory:
app.Static("/", "./files")
```
You can use any virtual path prefix \(_where the path does not actually exist in the file system_\) for files that are served by the **Static** method, specify a prefix path for the static directory, as shown below:
```go title="Examples"
app.Static("/static", "./public")
// => http://localhost:3000/static/hello.html
// => http://localhost:3000/static/js/jquery.js
// => http://localhost:3000/static/css/style.css
```
If you want to have a little bit more control regarding the settings for serving static files. You could use the `fiber.Static` struct to enable specific settings.
```go title="fiber.Static{}"
// Static defines configuration options when defining static assets.
type Static struct {
// When set to true, the server tries minimizing CPU usage by caching compressed files.
// This works differently than the github.com/gofiber/compression middleware.
// Optional. Default value false
Compress bool `json:"compress"`
// When set to true, enables byte range requests.
// Optional. Default value false
ByteRange bool `json:"byte_range"`
// When set to true, enables directory browsing.
// Optional. Default value false.
Browse bool `json:"browse"`
// When set to true, enables direct download.
// Optional. Default value false.
Download bool `json:"download"`
// The name of the index file for serving a directory.
// Optional. Default value "index.html".
Index string `json:"index"`
// Expiration duration for inactive file handlers.
// Use a negative time.Duration to disable it.
//
// Optional. Default value 10 * time.Second.
CacheDuration time.Duration `json:"cache_duration"`
// The value for the Cache-Control HTTP-header
// that is set on the file response. MaxAge is defined in seconds.
//
// Optional. Default value 0.
MaxAge int `json:"max_age"`
// ModifyResponse defines a function that allows you to alter the response.
//
// Optional. Default: nil
ModifyResponse Handler
// Next defines a function to skip this middleware when returned true.
//
// Optional. Default: nil
Next func(c *Ctx) bool
}
```
```go title="Example"
// Custom config
app.Static("/", "./public", fiber.Static{
Compress: true,
ByteRange: true,
Browse: true,
Index: "john.html",
CacheDuration: 10 * time.Second,
MaxAge: 3600,
})
```
## Route Handlers
<RoutingHandler />
## Mount
You can Mount Fiber instance by creating a `*Mount`
```go title="Signature"
func (a *App) Mount(prefix string, app *App) Router
```
```go title="Examples"
func main() {
app := fiber.New()
micro := fiber.New()
app.Mount("/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.
```go title="Signature"
func (app *App) MountPath() string
```
```go title="Examples"
func main() {
app := fiber.New()
one := fiber.New()
two := fiber.New()
three := fiber.New()
two.Mount("/three", three)
one.Mount("/two", two)
app.Mount("/one", one)
one.MountPath() // "/one"
two.MountPath() // "/one/two"
three.MountPath() // "/one/two/three"
app.MountPath() // ""
}
```
:::caution
Mounting order is important for MountPath. If you want to get mount paths properly, you should start mounting from the deepest app.
:::
## Group
You can group routes by creating a `*Group` struct.
```go title="Signature"
func (app *App) Group(prefix string, handlers ...Handler) Router
```
```go title="Examples"
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"))
}
```
## Route
You can define routes with a common prefix inside the common function.
```go title="Signature"
func (app *App) Route(prefix string, fn func(router Router), name ...string) Router
```
```go title="Examples"
func main() {
app := fiber.New()
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.")
log.Fatal(app.Listen(":3000"))
}
```
## Server
Server returns the underlying [fasthttp server](https://godoc.org/github.com/valyala/fasthttp#Server)
```go title="Signature"
func (app *App) Server() *fasthttp.Server
```
```go title="Examples"
func main() {
app := fiber.New()
app.Server().MaxConnsPerIP = 1
// ...
}
```
## Server Shutdown
Shutdown gracefully shuts down the server without interrupting any active connections. Shutdown works by first closing all open listeners and then waits indefinitely for all connections to return to idle before shutting down.
ShutdownWithTimeout will forcefully close any active connections after the timeout expires.
ShutdownWithContext shuts down the server including by force if the context's deadline is exceeded.
```go
func (app *App) Shutdown() error
func (app *App) ShutdownWithTimeout(timeout time.Duration) error
func (app *App) ShutdownWithContext(ctx context.Context) error
```
## HandlersCount
This method returns the amount of registered handlers.
```go title="Signature"
func (app *App) HandlersCount() uint32
```
## Stack
This method returns the original router stack
```go title="Signature"
func (app *App) Stack() [][]*Route
```
```go title="Examples"
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))
app.Listen(":3000")
}
```
```javascript title="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 of latest created route.
```go title="Signature"
func (app *App) Name(name string) Router
```
```go title="Examples"
var handler = func(c *fiber.Ctx) error { return nil }
func main() {
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.Print(string(data))
app.Listen(":3000")
}
```
```javascript title="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 gets the route by name.
```go title="Signature"
func (app *App) GetRoute(name string) Route
```
```go title="Examples"
var handler = func(c *fiber.Ctx) error { return nil }
func main() {
app := fiber.New()
app.Get("/", handler).Name("index")
data, _ := json.MarshalIndent(app.GetRoute("index"), "", " ")
fmt.Print(string(data))
app.Listen(":3000")
}
```
```javascript title="Result"
{
"method": "GET",
"name": "index",
"path": "/",
"params": null
}
```
## GetRoutes
This method gets all routes.
```go title="Signature"
func (app *App) GetRoutes(filterUseOption ...bool) []Route
```
When filterUseOption equal to true, it will filter the routes registered by the middleware.
```go title="Examples"
func main() {
app := fiber.New()
app.Post("/", func (c *fiber.Ctx) error {
return c.SendString("Hello, World!")
}).Name("index")
data, _ := json.MarshalIndent(app.GetRoutes(true), "", " ")
fmt.Print(string(data))
}
```
```javascript title="Result"
[
{
"method": "POST",
"name": "index",
"path": "/",
"params": null
}
]
```
## Config
Config returns the app config as value \( read-only \).
```go title="Signature"
func (app *App) Config() Config
```
## Handler
Handler returns the server handler that can be used to serve custom \*fasthttp.RequestCtx requests.
```go title="Signature"
func (app *App) Handler() fasthttp.RequestHandler
```
## Listen
Listen serves HTTP requests from the given address.
```go title="Signature"
func (app *App) Listen(addr string) error
```
```go title="Examples"
// Listen on port :8080
app.Listen(":8080")
// Custom host
app.Listen("127.0.0.1:8080")
```
## ListenTLS
ListenTLS serves HTTPs requests from the given address using certFile and keyFile paths to as TLS certificate and key file.
```go title="Signature"
func (app *App) ListenTLS(addr, certFile, keyFile string) error
```
```go title="Examples"
app.ListenTLS(":443", "./cert.pem", "./cert.key");
```
Using `ListenTLS` defaults to the following config \( use `Listener` to provide your own config \)
```go title="Default \*tls.Config"
&tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{
cert,
},
}
```
## ListenTLSWithCertificate
```go title="Signature"
func (app *App) ListenTLS(addr string, cert tls.Certificate) error
```
```go title="Examples"
app.ListenTLSWithCertificate(":443", cert);
```
Using `ListenTLSWithCertificate` defaults to the following config \( use `Listener` to provide your own config \)
```go title="Default \*tls.Config"
&tls.Config{
MinVersion: tls.VersionTLS12,
Certificates: []tls.Certificate{
cert,
},
}
```
## ListenMutualTLS
ListenMutualTLS serves HTTPs requests from the given address using certFile, keyFile and clientCertFile are the paths to TLS certificate and key file
```go title="Signature"
func (app *App) ListenMutualTLS(addr, certFile, keyFile, clientCertFile string) error
```
```go title="Examples"
app.ListenMutualTLS(":443", "./cert.pem", "./cert.key", "./ca-chain-cert.pem");
```
Using `ListenMutualTLS` defaults to the following config \( use `Listener` to provide your own config \)
```go title="Default \*tls.Config"
&tls.Config{
MinVersion: tls.VersionTLS12,
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: clientCertPool,
Certificates: []tls.Certificate{
cert,
},
}
```
## ListenMutualTLSWithCertificate
ListenMutualTLSWithCertificate serves HTTPs requests from the given address using certFile, keyFile and clientCertFile are the paths to TLS certificate and key file
```go title="Signature"
func (app *App) ListenMutualTLSWithCertificate(addr string, cert tls.Certificate, clientCertPool *x509.CertPool) error
```
```go title="Examples"
app.ListenMutualTLSWithCertificate(":443", cert, clientCertPool);
```
Using `ListenMutualTLSWithCertificate` defaults to the following config \( use `Listener` to provide your own config \)
```go title="Default \*tls.Config"
&tls.Config{
MinVersion: tls.VersionTLS12,
ClientAuth: tls.RequireAndVerifyClientCert,
ClientCAs: clientCertPool,
Certificates: []tls.Certificate{
cert,
},
}
```
## Listener
You can pass your own [`net.Listener`](https://pkg.go.dev/net/#Listener) using the `Listener` method. This method can be used to enable **TLS/HTTPS** with a custom tls.Config.
```go title="Signature"
func (app *App) Listener(ln net.Listener) error
```
```go title="Examples"
ln, _ := net.Listen("tcp", ":3000")
cer, _:= tls.LoadX509KeyPair("server.crt", "server.key")
ln = tls.NewListener(ln, &tls.Config{Certificates: []tls.Certificate{cer}})
app.Listener(ln)
```
## 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` if you want to disable a timeout altogether, pass `-1` as a second argument.
```go title="Signature"
func (app *App) Test(req *http.Request, msTimeout ...int) (*http.Response, error)
```
```go title="Examples"
// 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!")
})
// http.Request
req := httptest.NewRequest("GET", "http://google.com", nil)
req.Header.Set("X-Custom-Header", "hi")
// http.Response
resp, _ := app.Test(req)
// Do something with results:
if resp.StatusCode == fiber.StatusOK {
body, _ := io.ReadAll(resp.Body)
fmt.Println(string(body)) // => Hello, World!
}
```
## Hooks
Hooks is a method to return [hooks](../guide/hooks.md) property.
```go title="Signature"
func (app *App) Hooks() *Hooks
```

663
docs/api/client.md Normal file
View file

@ -0,0 +1,663 @@
---
id: client
title: 🌎 Client
description: The Client struct represents the Fiber HTTP Client.
sidebar_position: 5
---
## Start request
Start a http request with http method and url.
```go title="Signatures"
// Client http methods
func (c *Client) Get(url string) *Agent
func (c *Client) Head(url string) *Agent
func (c *Client) Post(url string) *Agent
func (c *Client) Put(url string) *Agent
func (c *Client) Patch(url string) *Agent
func (c *Client) Delete(url string) *Agent
```
Here we present a brief example demonstrating the simulation of a proxy using our `*fiber.Agent` methods.
```go
// Get something
func getSomething(c *fiber.Ctx) (err error) {
agent := fiber.Get("<URL>")
statusCode, body, errs := agent.Bytes()
if len(errs) > 0 {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"errs": errs,
})
}
var something fiber.Map
err = json.Unmarshal(body, &something)
if err != nil {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"err": err,
})
}
return c.Status(statusCode).JSON(something)
}
// Post something
func createSomething(c *fiber.Ctx) (err error) {
agent := fiber.Post("<URL>")
agent.Body(c.Body()) // set body received by request
statusCode, body, errs := agent.Bytes()
if len(errs) > 0 {
return c.Status(fiber.StatusInternalServerError).JSON(fiber.Map{
"errs": errs,
})
}
// pass status code and body received by the proxy
return c.Status(statusCode).Send(body)
}
```
Based on this short example, we can perceive that using the `*fiber.Client` is very straightforward and intuitive.
## ✨ Agent
`Agent` is built on top of FastHTTP's [`HostClient`](https://github.com/valyala/fasthttp/blob/master/client.go#L603) which has lots of convenient helper methods such as dedicated methods for request methods.
### Parse
Parse initializes a HostClient.
```go title="Parse"
a := AcquireAgent()
req := a.Request()
req.Header.SetMethod(MethodGet)
req.SetRequestURI("http://example.com")
if err := a.Parse(); err != nil {
panic(err)
}
code, body, errs := a.Bytes() // ...
```
### Set
Set sets the given `key: value` header.
```go title="Signature"
func (a *Agent) Set(k, v string) *Agent
func (a *Agent) SetBytesK(k []byte, v string) *Agent
func (a *Agent) SetBytesV(k string, v []byte) *Agent
func (a *Agent) SetBytesKV(k []byte, v []byte) *Agent
```
```go title="Example"
agent.Set("k1", "v1").
SetBytesK([]byte("k1"), "v1").
SetBytesV("k1", []byte("v1")).
SetBytesKV([]byte("k2"), []byte("v2"))
// ...
```
### Add
Add adds the given `key: value` header. Multiple headers with the same key may be added with this function.
```go title="Signature"
func (a *Agent) Add(k, v string) *Agent
func (a *Agent) AddBytesK(k []byte, v string) *Agent
func (a *Agent) AddBytesV(k string, v []byte) *Agent
func (a *Agent) AddBytesKV(k []byte, v []byte) *Agent
```
```go title="Example"
agent.Add("k1", "v1").
AddBytesK([]byte("k1"), "v1").
AddBytesV("k1", []byte("v1")).
AddBytesKV([]byte("k2"), []byte("v2"))
// Headers:
// K1: v1
// K1: v1
// K1: v1
// K2: v2
```
### ConnectionClose
ConnectionClose adds the `Connection: close` header.
```go title="Signature"
func (a *Agent) ConnectionClose() *Agent
```
```go title="Example"
agent.ConnectionClose()
// ...
```
### UserAgent
UserAgent sets `User-Agent` header value.
```go title="Signature"
func (a *Agent) UserAgent(userAgent string) *Agent
func (a *Agent) UserAgentBytes(userAgent []byte) *Agent
```
```go title="Example"
agent.UserAgent("fiber")
// ...
```
### Cookie
Cookie sets a cookie in `key: value` form. `Cookies` can be used to set multiple cookies.
```go title="Signature"
func (a *Agent) Cookie(key, value string) *Agent
func (a *Agent) CookieBytesK(key []byte, value string) *Agent
func (a *Agent) CookieBytesKV(key, value []byte) *Agent
func (a *Agent) Cookies(kv ...string) *Agent
func (a *Agent) CookiesBytesKV(kv ...[]byte) *Agent
```
```go title="Example"
agent.Cookie("k", "v")
agent.Cookies("k1", "v1", "k2", "v2")
// ...
```
### Referer
Referer sets the Referer header value.
```go title="Signature"
func (a *Agent) Referer(referer string) *Agent
func (a *Agent) RefererBytes(referer []byte) *Agent
```
```go title="Example"
agent.Referer("https://docs.gofiber.io")
// ...
```
### ContentType
ContentType sets Content-Type header value.
```go title="Signature"
func (a *Agent) ContentType(contentType string) *Agent
func (a *Agent) ContentTypeBytes(contentType []byte) *Agent
```
```go title="Example"
agent.ContentType("custom-type")
// ...
```
### Host
Host sets the Host header.
```go title="Signature"
func (a *Agent) Host(host string) *Agent
func (a *Agent) HostBytes(host []byte) *Agent
```
```go title="Example"
agent.Host("example.com")
// ...
```
### QueryString
QueryString sets the URI query string.
```go title="Signature"
func (a *Agent) QueryString(queryString string) *Agent
func (a *Agent) QueryStringBytes(queryString []byte) *Agent
```
```go title="Example"
agent.QueryString("foo=bar")
// ...
```
### BasicAuth
BasicAuth sets the URI username and password using HTTP Basic Auth.
```go title="Signature"
func (a *Agent) BasicAuth(username, password string) *Agent
func (a *Agent) BasicAuthBytes(username, password []byte) *Agent
```
```go title="Example"
agent.BasicAuth("foo", "bar")
// ...
```
### Body
There are several ways to set request body.
```go title="Signature"
func (a *Agent) BodyString(bodyString string) *Agent
func (a *Agent) Body(body []byte) *Agent
// BodyStream sets request body stream and, optionally body size.
//
// If bodySize is >= 0, then the bodyStream must provide exactly bodySize bytes
// before returning io.EOF.
//
// If bodySize < 0, then bodyStream is read until io.EOF.
//
// bodyStream.Close() is called after finishing reading all body data
// if it implements io.Closer.
//
// Note that GET and HEAD requests cannot have body.
func (a *Agent) BodyStream(bodyStream io.Reader, bodySize int) *Agent
```
```go title="Example"
agent.BodyString("foo=bar")
agent.Body([]byte("bar=baz"))
agent.BodyStream(strings.NewReader("body=stream"), -1)
// ...
```
### JSON
JSON sends a JSON request by setting the Content-Type header to the `ctype` parameter. If no `ctype` is passed in, the header is set to `application/json`.
```go title="Signature"
func (a *Agent) JSON(v interface{}, ctype ...string) *Agent
```
```go title="Example"
agent.JSON(fiber.Map{"success": true})
// ...
```
### XML
XML sends an XML request by setting the Content-Type header to `application/xml`.
```go title="Signature"
func (a *Agent) XML(v interface{}) *Agent
```
```go title="Example"
agent.XML(fiber.Map{"success": true})
// ...
```
### Form
Form sends a form request by setting the Content-Type header to `application/x-www-form-urlencoded`.
```go title="Signature"
// Form sends form request with body if args is non-nil.
//
// It is recommended obtaining args via AcquireArgs and release it
// manually in performance-critical code.
func (a *Agent) Form(args *Args) *Agent
```
```go title="Example"
args := AcquireArgs()
args.Set("foo", "bar")
agent.Form(args)
// ...
ReleaseArgs(args)
```
### MultipartForm
MultipartForm sends multipart form request by setting the Content-Type header to `multipart/form-data`. These requests can include key-value's and files.
```go title="Signature"
// MultipartForm sends multipart form request with k-v and files.
//
// It is recommended to obtain args via AcquireArgs and release it
// manually in performance-critical code.
func (a *Agent) MultipartForm(args *Args) *Agent
```
```go title="Example"
args := AcquireArgs()
args.Set("foo", "bar")
agent.MultipartForm(args)
// ...
ReleaseArgs(args)
```
Fiber provides several methods for sending files. Note that they must be called before `MultipartForm`.
#### Boundary
Boundary sets boundary for multipart form request.
```go title="Signature"
func (a *Agent) Boundary(boundary string) *Agent
```
```go title="Example"
agent.Boundary("myBoundary")
.MultipartForm(nil)
// ...
```
#### SendFile\(s\)
SendFile read a file and appends it to a multipart form request. Sendfiles can be used to append multiple files.
```go title="Signature"
func (a *Agent) SendFile(filename string, fieldname ...string) *Agent
func (a *Agent) SendFiles(filenamesAndFieldnames ...string) *Agent
```
```go title="Example"
agent.SendFile("f", "field name")
.SendFiles("f1", "field name1", "f2").
.MultipartForm(nil)
// ...
```
#### FileData
FileData appends file data for multipart form request.
```go
// FormFile represents multipart form file
type FormFile struct {
// Fieldname is form file's field name
Fieldname string
// Name is form file's name
Name string
// Content is form file's content
Content []byte
}
```
```go title="Signature"
// FileData appends files for multipart form request.
//
// It is recommended obtaining formFile via AcquireFormFile and release it
// manually in performance-critical code.
func (a *Agent) FileData(formFiles ...*FormFile) *Agent
```
```go title="Example"
ff1 := &FormFile{"filename1", "field name1", []byte("content")}
ff2 := &FormFile{"filename2", "field name2", []byte("content")}
agent.FileData(ff1, ff2).
MultipartForm(nil)
// ...
```
### Debug
Debug mode enables logging request and response detail to `io.writer`\(default is `os.Stdout`\).
```go title="Signature"
func (a *Agent) Debug(w ...io.Writer) *Agent
```
```go title="Example"
agent.Debug()
// ...
```
### Timeout
Timeout sets request timeout duration.
```go title="Signature"
func (a *Agent) Timeout(timeout time.Duration) *Agent
```
```go title="Example"
agent.Timeout(time.Second)
// ...
```
### Reuse
Reuse enables the Agent instance to be used again after one request. If agent is reusable, then it should be released manually when it is no longer used.
```go title="Signature"
func (a *Agent) Reuse() *Agent
```
```go title="Example"
agent.Reuse()
// ...
```
### InsecureSkipVerify
InsecureSkipVerify controls whether the Agent verifies the server certificate chain and host name.
```go title="Signature"
func (a *Agent) InsecureSkipVerify() *Agent
```
```go title="Example"
agent.InsecureSkipVerify()
// ...
```
### TLSConfig
TLSConfig sets tls config.
```go title="Signature"
func (a *Agent) TLSConfig(config *tls.Config) *Agent
```
```go title="Example"
// Create tls certificate
cer, _ := tls.LoadX509KeyPair("pem", "key")
config := &tls.Config{
Certificates: []tls.Certificate{cer},
}
agent.TLSConfig(config)
// ...
```
### MaxRedirectsCount
MaxRedirectsCount sets max redirect count for GET and HEAD.
```go title="Signature"
func (a *Agent) MaxRedirectsCount(count int) *Agent
```
```go title="Example"
agent.MaxRedirectsCount(7)
// ...
```
### JSONEncoder
JSONEncoder sets custom json encoder.
```go title="Signature"
func (a *Agent) JSONEncoder(jsonEncoder utils.JSONMarshal) *Agent
```
```go title="Example"
agent.JSONEncoder(json.Marshal)
// ...
```
### JSONDecoder
JSONDecoder sets custom json decoder.
```go title="Signature"
func (a *Agent) JSONDecoder(jsonDecoder utils.JSONUnmarshal) *Agent
```
```go title="Example"
agent.JSONDecoder(json.Unmarshal)
// ...
```
### Request
Request returns Agent request instance.
```go title="Signature"
func (a *Agent) Request() *Request
```
```go title="Example"
req := agent.Request()
// ...
```
### SetResponse
SetResponse sets custom response for the Agent instance. It is recommended obtaining custom response via AcquireResponse and release it manually in performance-critical code.
```go title="Signature"
func (a *Agent) SetResponse(customResp *Response) *Agent
```
```go title="Example"
resp := AcquireResponse()
agent.SetResponse(resp)
// ...
ReleaseResponse(resp)
```
<details>
<summary>Example handling for response values</summary>
```go title="Example handling response"
// Create a Fiber HTTP client agent
agent := fiber.Get("https://httpbin.org/get")
// Acquire a response object to store the result
resp := fiber.AcquireResponse()
agent.SetResponse(resp)
// Perform the HTTP GET request
code, body, errs := agent.String()
if errs != nil {
// Handle any errors that occur during the request
panic(errs)
}
// Print the HTTP response code and body
fmt.Println("Response Code:", code)
fmt.Println("Response Body:", body)
// Visit and print all the headers in the response
resp.Header.VisitAll(func(key, value []byte) {
fmt.Println("Header", string(key), "value", string(value))
})
// Release the response to free up resources
fiber.ReleaseResponse(resp)
```
Output:
```txt title="Output"
Response Code: 200
Response Body: {
"args": {},
"headers": {
"Host": "httpbin.org",
"User-Agent": "fiber",
"X-Amzn-Trace-Id": "Root=1-653763d0-2555d5ba3838f1e9092f9f72"
},
"origin": "83.137.191.1",
"url": "https://httpbin.org/get"
}
Header Content-Length value 226
Header Content-Type value application/json
Header Server value gunicorn/19.9.0
Header Date value Tue, 24 Oct 2023 06:27:28 GMT
Header Connection value keep-alive
Header Access-Control-Allow-Origin value *
Header Access-Control-Allow-Credentials value true
```
</details>
### Dest
Dest sets custom dest. The contents of dest will be replaced by the response body, if the dest is too small a new slice will be allocated.
```go title="Signature"
func (a *Agent) Dest(dest []byte) *Agent {
```
```go title="Example"
agent.Dest(nil)
// ...
```
### Bytes
Bytes returns the status code, bytes body and errors of url.
```go title="Signature"
func (a *Agent) Bytes() (code int, body []byte, errs []error)
```
```go title="Example"
code, body, errs := agent.Bytes()
// ...
```
### String
String returns the status code, string body and errors of url.
```go title="Signature"
func (a *Agent) String() (int, string, []error)
```
```go title="Example"
code, body, errs := agent.String()
// ...
```
### Struct
Struct returns the status code, bytes body and errors of url. And bytes body will be unmarshalled to given v.
```go title="Signature"
func (a *Agent) Struct(v interface{}) (code int, body []byte, errs []error)
```
```go title="Example"
var d data
code, body, errs := agent.Struct(&d)
// ...
```
### RetryIf
RetryIf controls whether a retry should be attempted after an error.
By default, will use isIdempotent function from fasthttp
```go title="Signature"
func (a *Agent) RetryIf(retryIf RetryIfFunc) *Agent
```
```go title="Example"
agent.Get("https://example.com").RetryIf(func (req *fiber.Request) bool {
return req.URI() == "https://example.com"
})
// ...
```

291
docs/api/constants.md Normal file
View file

@ -0,0 +1,291 @@
---
id: constants
title: 📋 Constants
description: Some constants for Fiber.
sidebar_position: 4
---
HTTP methods were copied from net/http.
```go
const (
MethodGet = "GET" // RFC 7231, 4.3.1
MethodHead = "HEAD" // RFC 7231, 4.3.2
MethodPost = "POST" // RFC 7231, 4.3.3
MethodPut = "PUT" // RFC 7231, 4.3.4
MethodPatch = "PATCH" // RFC 5789
MethodDelete = "DELETE" // RFC 7231, 4.3.5
MethodConnect = "CONNECT" // RFC 7231, 4.3.6
MethodOptions = "OPTIONS" // RFC 7231, 4.3.7
MethodTrace = "TRACE" // RFC 7231, 4.3.8
methodUse = "USE"
)
```
MIME types that are commonly used
```go
const (
MIMETextXML = "text/xml"
MIMETextHTML = "text/html"
MIMETextPlain = "text/plain"
MIMEApplicationXML = "application/xml"
MIMEApplicationJSON = "application/json"
MIMEApplicationJavaScript = "application/javascript"
MIMEApplicationForm = "application/x-www-form-urlencoded"
MIMEOctetStream = "application/octet-stream"
MIMEMultipartForm = "multipart/form-data"
MIMETextXMLCharsetUTF8 = "text/xml; charset=utf-8"
MIMETextHTMLCharsetUTF8 = "text/html; charset=utf-8"
MIMETextPlainCharsetUTF8 = "text/plain; charset=utf-8"
MIMEApplicationXMLCharsetUTF8 = "application/xml; charset=utf-8"
MIMEApplicationJSONCharsetUTF8 = "application/json; charset=utf-8"
MIMEApplicationJavaScriptCharsetUTF8 = "application/javascript; charset=utf-8"
)
```
HTTP status codes were copied from net/http.
```go
const (
StatusContinue = 100 // RFC 7231, 6.2.1
StatusSwitchingProtocols = 101 // RFC 7231, 6.2.2
StatusProcessing = 102 // RFC 2518, 10.1
StatusEarlyHints = 103 // RFC 8297
StatusOK = 200 // RFC 7231, 6.3.1
StatusCreated = 201 // RFC 7231, 6.3.2
StatusAccepted = 202 // RFC 7231, 6.3.3
StatusNonAuthoritativeInformation = 203 // RFC 7231, 6.3.4
StatusNoContent = 204 // RFC 7231, 6.3.5
StatusResetContent = 205 // RFC 7231, 6.3.6
StatusPartialContent = 206 // RFC 7233, 4.1
StatusMultiStatus = 207 // RFC 4918, 11.1
StatusAlreadyReported = 208 // RFC 5842, 7.1
StatusIMUsed = 226 // RFC 3229, 10.4.1
StatusMultipleChoices = 300 // RFC 7231, 6.4.1
StatusMovedPermanently = 301 // RFC 7231, 6.4.2
StatusFound = 302 // RFC 7231, 6.4.3
StatusSeeOther = 303 // RFC 7231, 6.4.4
StatusNotModified = 304 // RFC 7232, 4.1
StatusUseProxy = 305 // RFC 7231, 6.4.5
StatusTemporaryRedirect = 307 // RFC 7231, 6.4.7
StatusPermanentRedirect = 308 // RFC 7538, 3
StatusBadRequest = 400 // RFC 7231, 6.5.1
StatusUnauthorized = 401 // RFC 7235, 3.1
StatusPaymentRequired = 402 // RFC 7231, 6.5.2
StatusForbidden = 403 // RFC 7231, 6.5.3
StatusNotFound = 404 // RFC 7231, 6.5.4
StatusMethodNotAllowed = 405 // RFC 7231, 6.5.5
StatusNotAcceptable = 406 // RFC 7231, 6.5.6
StatusProxyAuthRequired = 407 // RFC 7235, 3.2
StatusRequestTimeout = 408 // RFC 7231, 6.5.7
StatusConflict = 409 // RFC 7231, 6.5.8
StatusGone = 410 // RFC 7231, 6.5.9
StatusLengthRequired = 411 // RFC 7231, 6.5.10
StatusPreconditionFailed = 412 // RFC 7232, 4.2
StatusRequestEntityTooLarge = 413 // RFC 7231, 6.5.11
StatusRequestURITooLong = 414 // RFC 7231, 6.5.12
StatusUnsupportedMediaType = 415 // RFC 7231, 6.5.13
StatusRequestedRangeNotSatisfiable = 416 // RFC 7233, 4.4
StatusExpectationFailed = 417 // RFC 7231, 6.5.14
StatusTeapot = 418 // RFC 7168, 2.3.3
StatusMisdirectedRequest = 421 // RFC 7540, 9.1.2
StatusUnprocessableEntity = 422 // RFC 4918, 11.2
StatusLocked = 423 // RFC 4918, 11.3
StatusFailedDependency = 424 // RFC 4918, 11.4
StatusTooEarly = 425 // RFC 8470, 5.2.
StatusUpgradeRequired = 426 // RFC 7231, 6.5.15
StatusPreconditionRequired = 428 // RFC 6585, 3
StatusTooManyRequests = 429 // RFC 6585, 4
StatusRequestHeaderFieldsTooLarge = 431 // RFC 6585, 5
StatusUnavailableForLegalReasons = 451 // RFC 7725, 3
StatusInternalServerError = 500 // RFC 7231, 6.6.1
StatusNotImplemented = 501 // RFC 7231, 6.6.2
StatusBadGateway = 502 // RFC 7231, 6.6.3
StatusServiceUnavailable = 503 // RFC 7231, 6.6.4
StatusGatewayTimeout = 504 // RFC 7231, 6.6.5
StatusHTTPVersionNotSupported = 505 // RFC 7231, 6.6.6
StatusVariantAlsoNegotiates = 506 // RFC 2295, 8.1
StatusInsufficientStorage = 507 // RFC 4918, 11.5
StatusLoopDetected = 508 // RFC 5842, 7.2
StatusNotExtended = 510 // RFC 2774, 7
StatusNetworkAuthenticationRequired = 511 // RFC 6585, 6
)
```
Errors
```go
var (
ErrBadRequest = NewError(StatusBadRequest) // RFC 7231, 6.5.1
ErrUnauthorized = NewError(StatusUnauthorized) // RFC 7235, 3.1
ErrPaymentRequired = NewError(StatusPaymentRequired) // RFC 7231, 6.5.2
ErrForbidden = NewError(StatusForbidden) // RFC 7231, 6.5.3
ErrNotFound = NewError(StatusNotFound) // RFC 7231, 6.5.4
ErrMethodNotAllowed = NewError(StatusMethodNotAllowed) // RFC 7231, 6.5.5
ErrNotAcceptable = NewError(StatusNotAcceptable) // RFC 7231, 6.5.6
ErrProxyAuthRequired = NewError(StatusProxyAuthRequired) // RFC 7235, 3.2
ErrRequestTimeout = NewError(StatusRequestTimeout) // RFC 7231, 6.5.7
ErrConflict = NewError(StatusConflict) // RFC 7231, 6.5.8
ErrGone = NewError(StatusGone) // RFC 7231, 6.5.9
ErrLengthRequired = NewError(StatusLengthRequired) // RFC 7231, 6.5.10
ErrPreconditionFailed = NewError(StatusPreconditionFailed) // RFC 7232, 4.2
ErrRequestEntityTooLarge = NewError(StatusRequestEntityTooLarge) // RFC 7231, 6.5.11
ErrRequestURITooLong = NewError(StatusRequestURITooLong) // RFC 7231, 6.5.12
ErrUnsupportedMediaType = NewError(StatusUnsupportedMediaType) // RFC 7231, 6.5.13
ErrRequestedRangeNotSatisfiable = NewError(StatusRequestedRangeNotSatisfiable) // RFC 7233, 4.4
ErrExpectationFailed = NewError(StatusExpectationFailed) // RFC 7231, 6.5.14
ErrTeapot = NewError(StatusTeapot) // RFC 7168, 2.3.3
ErrMisdirectedRequest = NewError(StatusMisdirectedRequest) // RFC 7540, 9.1.2
ErrUnprocessableEntity = NewError(StatusUnprocessableEntity) // RFC 4918, 11.2
ErrLocked = NewError(StatusLocked) // RFC 4918, 11.3
ErrFailedDependency = NewError(StatusFailedDependency) // RFC 4918, 11.4
ErrTooEarly = NewError(StatusTooEarly) // RFC 8470, 5.2.
ErrUpgradeRequired = NewError(StatusUpgradeRequired) // RFC 7231, 6.5.15
ErrPreconditionRequired = NewError(StatusPreconditionRequired) // RFC 6585, 3
ErrTooManyRequests = NewError(StatusTooManyRequests) // RFC 6585, 4
ErrRequestHeaderFieldsTooLarge = NewError(StatusRequestHeaderFieldsTooLarge) // RFC 6585, 5
ErrUnavailableForLegalReasons = NewError(StatusUnavailableForLegalReasons) // RFC 7725, 3
ErrInternalServerError = NewError(StatusInternalServerError) // RFC 7231, 6.6.1
ErrNotImplemented = NewError(StatusNotImplemented) // RFC 7231, 6.6.2
ErrBadGateway = NewError(StatusBadGateway) // RFC 7231, 6.6.3
ErrServiceUnavailable = NewError(StatusServiceUnavailable) // RFC 7231, 6.6.4
ErrGatewayTimeout = NewError(StatusGatewayTimeout) // RFC 7231, 6.6.5
ErrHTTPVersionNotSupported = NewError(StatusHTTPVersionNotSupported) // RFC 7231, 6.6.6
ErrVariantAlsoNegotiates = NewError(StatusVariantAlsoNegotiates) // RFC 2295, 8.1
ErrInsufficientStorage = NewError(StatusInsufficientStorage) // RFC 4918, 11.5
ErrLoopDetected = NewError(StatusLoopDetected) // RFC 5842, 7.2
ErrNotExtended = NewError(StatusNotExtended) // RFC 2774, 7
ErrNetworkAuthenticationRequired = NewError(StatusNetworkAuthenticationRequired) // RFC 6585, 6
)
```
HTTP Headers were copied from net/http.
```go
const (
HeaderAuthorization = "Authorization"
HeaderProxyAuthenticate = "Proxy-Authenticate"
HeaderProxyAuthorization = "Proxy-Authorization"
HeaderWWWAuthenticate = "WWW-Authenticate"
HeaderAge = "Age"
HeaderCacheControl = "Cache-Control"
HeaderClearSiteData = "Clear-Site-Data"
HeaderExpires = "Expires"
HeaderPragma = "Pragma"
HeaderWarning = "Warning"
HeaderAcceptCH = "Accept-CH"
HeaderAcceptCHLifetime = "Accept-CH-Lifetime"
HeaderContentDPR = "Content-DPR"
HeaderDPR = "DPR"
HeaderEarlyData = "Early-Data"
HeaderSaveData = "Save-Data"
HeaderViewportWidth = "Viewport-Width"
HeaderWidth = "Width"
HeaderETag = "ETag"
HeaderIfMatch = "If-Match"
HeaderIfModifiedSince = "If-Modified-Since"
HeaderIfNoneMatch = "If-None-Match"
HeaderIfUnmodifiedSince = "If-Unmodified-Since"
HeaderLastModified = "Last-Modified"
HeaderVary = "Vary"
HeaderConnection = "Connection"
HeaderKeepAlive = "Keep-Alive"
HeaderAccept = "Accept"
HeaderAcceptCharset = "Accept-Charset"
HeaderAcceptEncoding = "Accept-Encoding"
HeaderAcceptLanguage = "Accept-Language"
HeaderCookie = "Cookie"
HeaderExpect = "Expect"
HeaderMaxForwards = "Max-Forwards"
HeaderSetCookie = "Set-Cookie"
HeaderAccessControlAllowCredentials = "Access-Control-Allow-Credentials"
HeaderAccessControlAllowHeaders = "Access-Control-Allow-Headers"
HeaderAccessControlAllowMethods = "Access-Control-Allow-Methods"
HeaderAccessControlAllowOrigin = "Access-Control-Allow-Origin"
HeaderAccessControlExposeHeaders = "Access-Control-Expose-Headers"
HeaderAccessControlMaxAge = "Access-Control-Max-Age"
HeaderAccessControlRequestHeaders = "Access-Control-Request-Headers"
HeaderAccessControlRequestMethod = "Access-Control-Request-Method"
HeaderOrigin = "Origin"
HeaderTimingAllowOrigin = "Timing-Allow-Origin"
HeaderXPermittedCrossDomainPolicies = "X-Permitted-Cross-Domain-Policies"
HeaderDNT = "DNT"
HeaderTk = "Tk"
HeaderContentDisposition = "Content-Disposition"
HeaderContentEncoding = "Content-Encoding"
HeaderContentLanguage = "Content-Language"
HeaderContentLength = "Content-Length"
HeaderContentLocation = "Content-Location"
HeaderContentType = "Content-Type"
HeaderForwarded = "Forwarded"
HeaderVia = "Via"
HeaderXForwardedFor = "X-Forwarded-For"
HeaderXForwardedHost = "X-Forwarded-Host"
HeaderXForwardedProto = "X-Forwarded-Proto"
HeaderXForwardedProtocol = "X-Forwarded-Protocol"
HeaderXForwardedSsl = "X-Forwarded-Ssl"
HeaderXUrlScheme = "X-Url-Scheme"
HeaderLocation = "Location"
HeaderFrom = "From"
HeaderHost = "Host"
HeaderReferer = "Referer"
HeaderReferrerPolicy = "Referrer-Policy"
HeaderUserAgent = "User-Agent"
HeaderAllow = "Allow"
HeaderServer = "Server"
HeaderAcceptRanges = "Accept-Ranges"
HeaderContentRange = "Content-Range"
HeaderIfRange = "If-Range"
HeaderRange = "Range"
HeaderContentSecurityPolicy = "Content-Security-Policy"
HeaderContentSecurityPolicyReportOnly = "Content-Security-Policy-Report-Only"
HeaderCrossOriginResourcePolicy = "Cross-Origin-Resource-Policy"
HeaderExpectCT = "Expect-CT"
HeaderFeaturePolicy = "Feature-Policy"
HeaderPublicKeyPins = "Public-Key-Pins"
HeaderPublicKeyPinsReportOnly = "Public-Key-Pins-Report-Only"
HeaderStrictTransportSecurity = "Strict-Transport-Security"
HeaderUpgradeInsecureRequests = "Upgrade-Insecure-Requests"
HeaderXContentTypeOptions = "X-Content-Type-Options"
HeaderXDownloadOptions = "X-Download-Options"
HeaderXFrameOptions = "X-Frame-Options"
HeaderXPoweredBy = "X-Powered-By"
HeaderXXSSProtection = "X-XSS-Protection"
HeaderLastEventID = "Last-Event-ID"
HeaderNEL = "NEL"
HeaderPingFrom = "Ping-From"
HeaderPingTo = "Ping-To"
HeaderReportTo = "Report-To"
HeaderTE = "TE"
HeaderTrailer = "Trailer"
HeaderTransferEncoding = "Transfer-Encoding"
HeaderSecWebSocketAccept = "Sec-WebSocket-Accept"
HeaderSecWebSocketExtensions = "Sec-WebSocket-Extensions"
HeaderSecWebSocketKey = "Sec-WebSocket-Key"
HeaderSecWebSocketProtocol = "Sec-WebSocket-Protocol"
HeaderSecWebSocketVersion = "Sec-WebSocket-Version"
HeaderAcceptPatch = "Accept-Patch"
HeaderAcceptPushPolicy = "Accept-Push-Policy"
HeaderAcceptSignature = "Accept-Signature"
HeaderAltSvc = "Alt-Svc"
HeaderDate = "Date"
HeaderIndex = "Index"
HeaderLargeAllocation = "Large-Allocation"
HeaderLink = "Link"
HeaderPushPolicy = "Push-Policy"
HeaderRetryAfter = "Retry-After"
HeaderServerTiming = "Server-Timing"
HeaderSignature = "Signature"
HeaderSignedHeaders = "Signed-Headers"
HeaderSourceMap = "SourceMap"
HeaderUpgrade = "Upgrade"
HeaderXDNSPrefetchControl = "X-DNS-Prefetch-Control"
HeaderXPingback = "X-Pingback"
HeaderXRequestID = "X-Request-ID"
HeaderXRequestedWith = "X-Requested-With"
HeaderXRobotsTag = "X-Robots-Tag"
HeaderXUACompatible = "X-UA-Compatible"
)
```

2159
docs/api/ctx.md Normal file

File diff suppressed because it is too large Load diff

120
docs/api/fiber.md Normal file
View file

@ -0,0 +1,120 @@
---
id: fiber
title: 📦 Fiber
description: Fiber represents the fiber package where you start to create an instance.
sidebar_position: 1
---
## New
This method creates a new **App** named instance. You can pass optional [config ](#config)when creating a new instance.
```go title="Signature"
func New(config ...Config) *App
```
```go title="Example"
// Default config
app := fiber.New()
// ...
```
## Config
You can pass an optional Config when creating a new Fiber instance.
```go title="Example"
// Custom config
app := fiber.New(fiber.Config{
Prefork: true,
CaseSensitive: true,
StrictRouting: true,
ServerHeader: "Fiber",
AppName: "Test App v1.0.1",
})
// ...
```
**Config fields**
| Property | Type | Description | Default |
| ---------------------------- | --------------------- |--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| --------------------- |
| AppName | `string` | This allows to setup app name for the app | `""` |
| BodyLimit | `int` | Sets the maximum allowed size for a request body, if the size exceeds the configured limit, it sends `413 - Request Entity Too Large` response. | `4 * 1024 * 1024` |
| CaseSensitive | `bool` | When enabled, `/Foo` and `/foo` are different routes. When disabled, `/Foo`and `/foo` are treated the same. | `false` |
| ColorScheme | [`Colors`](https://github.com/gofiber/fiber/blob/master/color.go) | You can define custom color scheme. They'll be used for startup message, route list and some middlewares. | [`DefaultColors`](https://github.com/gofiber/fiber/blob/master/color.go) |
| CompressedFileSuffix | `string` | Adds a suffix to the original file name and tries saving the resulting compressed file under the new file name. | `".fiber.gz"` |
| Concurrency | `int` | Maximum number of concurrent connections. | `256 * 1024` |
| DisableDefaultContentType | `bool` | When set to true, causes the default Content-Type header to be excluded from the Response. | `false` |
| DisableDefaultDate | `bool` | When set to true causes the default date header to be excluded from the response. | `false` |
| DisableHeaderNormalizing | `bool` | By default all header names are normalized: conteNT-tYPE -&gt; Content-Type | `false` |
| DisableKeepalive | `bool` | Disable keep-alive connections, the server will close incoming connections after sending the first response to the client | `false` |
| DisablePreParseMultipartForm | `bool` | Will not pre parse Multipart Form data if set to true. This option is useful for servers that desire to treat multipart form data as a binary blob, or choose when to parse the data. | `false` |
| DisableStartupMessage | `bool` | When set to true, it will not print out debug information | `false` |
| ETag | `bool` | Enable or disable ETag header generation, since both weak and strong etags are generated using the same hashing method \(CRC-32\). Weak ETags are the default when enabled. | `false` |
| EnableIPValidation | `bool` | If set to true, `c.IP()` and `c.IPs()` will validate IP addresses before returning them. Also, `c.IP()` will return only the first valid IP rather than just the raw header value that may be a comma seperated string.<br /><br />**WARNING:** There is a small performance cost to doing this validation. Keep disabled if speed is your only concern and your application is behind a trusted proxy that already validates this header. | `false` |
| EnablePrintRoutes | `bool` | EnablePrintRoutes enables print all routes with their method, path, name and handler.. | `false` |
| EnableSplittingOnParsers | `bool` | EnableSplittingOnParsers splits the query/body/header parameters by comma when it's true. <br /> <br /> For example, you can use it to parse multiple values from a query parameter like this: `/api?foo=bar,baz == foo[]=bar&foo[]=baz` | `false` |
| EnableTrustedProxyCheck | `bool` | When set to true, fiber will check whether proxy is trusted, using TrustedProxies list. <br /><br />By default `c.Protocol()` will get value from X-Forwarded-Proto, X-Forwarded-Protocol, X-Forwarded-Ssl or X-Url-Scheme header, `c.IP()` will get value from `ProxyHeader` header, `c.Hostname()` will get value from X-Forwarded-Host header. <br /> If `EnableTrustedProxyCheck` is true, and `RemoteIP` is in the list of `TrustedProxies` `c.Protocol()`, `c.IP()`, and `c.Hostname()` will have the same behaviour when `EnableTrustedProxyCheck` disabled, if `RemoteIP` isn't in the list, `c.Protocol()` will return https in case when tls connection is handled by the app, or http otherwise, `c.IP()` will return RemoteIP() from fasthttp context, `c.Hostname()` will return `fasthttp.Request.URI().Host()` | `false` |
| ErrorHandler | `ErrorHandler` | ErrorHandler is executed when an error is returned from fiber.Handler. Mounted fiber error handlers are retained by the top-level app and applied on prefix associated requests. | `DefaultErrorHandler` |
| GETOnly | `bool` | Rejects all non-GET requests if set to true. This option is useful as anti-DoS protection for servers accepting only GET requests. The request size is limited by ReadBufferSize if GETOnly is set. | `false` |
| IdleTimeout | `time.Duration` | The maximum amount of time to wait for the next request when keep-alive is enabled. If IdleTimeout is zero, the value of ReadTimeout is used. | `nil` |
| Immutable | `bool` | When enabled, all values returned by context methods are immutable. By default, they are valid until you return from the handler; see issue [\#185](https://github.com/gofiber/fiber/issues/185). | `false` |
| JSONDecoder | `utils.JSONUnmarshal` | Allowing for flexibility in using another json library for decoding. | `json.Unmarshal` |
| JSONEncoder | `utils.JSONMarshal` | Allowing for flexibility in using another json library for encoding. | `json.Marshal` |
| Network | `string` | Known networks are "tcp", "tcp4" (IPv4-only), "tcp6" (IPv6-only)<br /><br />**WARNING:** When prefork is set to true, only "tcp4" and "tcp6" can be chosen. | `NetworkTCP4` |
| PassLocalsToViews | `bool` | PassLocalsToViews Enables passing of the locals set on a fiber.Ctx to the template engine. See our **Template Middleware** for supported engines. | `false` |
| Prefork | `bool` | Enables use of the[`SO_REUSEPORT`](https://lwn.net/Articles/542629/)socket option. This will spawn multiple Go processes listening on the same port. learn more about [socket sharding](https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1/). **NOTE: if enabled, the application will need to be ran through a shell because prefork mode sets environment variables. If you're using Docker, make sure the app is ran with `CMD ./app` or `CMD ["sh", "-c", "/app"]`. For more info, see** [**this**](https://github.com/gofiber/fiber/issues/1021#issuecomment-730537971) **issue comment.** | `false` |
| ProxyHeader | `string` | This 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-\*_. | `""` |
| ReadBufferSize | `int` | per-connection buffer size for requests' reading. This also limits the maximum header size. Increase this buffer if your clients send multi-KB RequestURIs and/or multi-KB headers \(for example, BIG cookies\). | `4096` |
| ReadTimeout | `time.Duration` | The amount of time allowed to read the full request, including the body. The default timeout is unlimited. | `nil` |
| RequestMethods | `[]string` | RequestMethods provides customizibility for HTTP methods. You can add/remove methods as you wish. | `DefaultMethods` |
| ServerHeader | `string` | Enables the `Server` HTTP header with the given value. | `""` |
| StreamRequestBody | `bool` | StreamRequestBody enables request body streaming, and calls the handler sooner when given body is larger then the current limit. | `false` |
| StrictRouting | `bool` | When enabled, the router treats `/foo` and `/foo/` as different. Otherwise, the router treats `/foo` and `/foo/` as the same. | `false` |
| TrustedProxies | `[]string` | Contains the list of trusted proxy IP's. Look at `EnableTrustedProxyCheck` doc. <br /> <br /> It can take IP or IP range addresses. If it gets IP range, it iterates all possible addresses. | `[]string*__*` |
| UnescapePath | `bool` | Converts all encoded characters in the route back before setting the path for the context, so that the routing can also work with URL encoded special characters | `false` |
| Views | `Views` | Views is the interface that wraps the Render function. See our **Template Middleware** for supported engines. | `nil` |
| ViewsLayout | `string` | Views Layout is the global layout for all template render until override on Render function. See our **Template Middleware** for supported engines. | `""` |
| WriteBufferSize | `int` | Per-connection buffer size for responses' writing. | `4096` |
| WriteTimeout | `time.Duration` | The maximum duration before timing out writes of the response. The default timeout is unlimited. | `nil` |
| XMLEncoder | `utils.XMLMarshal` | Allowing for flexibility in using another XML library for encoding. | `xml.Marshal` |
## NewError
NewError creates a new HTTPError instance with an optional message.
```go title="Signature"
func NewError(code int, message ...string) *Error
```
```go title="Example"
app.Get("/", func(c *fiber.Ctx) error {
return fiber.NewError(782, "Custom error message")
})
```
## IsChild
IsChild determines if the current process is a result of Prefork.
```go title="Signature"
func IsChild() bool
```
```go title="Example"
// Prefork will spawn child processes
app := fiber.New(fiber.Config{
Prefork: true,
})
if !fiber.IsChild() {
fmt.Println("I'm the parent process")
} else {
fmt.Println("I'm a child process")
}
// ...
```

155
docs/api/log.md Normal file
View file

@ -0,0 +1,155 @@
---
id: log
title: 📃 Log
description: Fiber's built-in log package
sidebar_position: 6
---
We can use logs to observe program behavior, diagnose problems, or configure corresponding alarms.
And defining a well structured log can improve search efficiency and facilitate handling of problems.
Fiber provides a default way to print logs in the standard output.
It also provides several global functions, such as `log.Info`, `log.Errorf`, `log.Warnw`, etc.
## Log levels
```go
const (
LevelTrace Level = iota
LevelDebug
LevelInfo
LevelWarn
LevelError
LevelFatal
LevelPanic
)
```
## Custom log
Fiber provides the `AllLogger` interface for adapting the various log libraries.
```go
type CommonLogger interface {
Logger
FormatLogger
WithLogger
}
type AllLogger interface {
CommonLogger
ControlLogger
WithLogger
}
```
## Print log
Note: The method of calling the Fatal level will interrupt the program running after printing the log, please use it with caution.
Directly print logs of different levels, which will be entered into messageKey, the default is msg.
```go
log.Info("Hello, World!")
log.Debug("Are you OK?")
log.Info("42 is the answer to life, the universe, and everything")
log.Warn("We are under attack!")
log.Error("Houston, we have a problem.")
log.Fatal("So Long, and Thanks for All the Fislog.")
log.Panic("The system is down.")
```
Format and print logs of different levels, all methods end with f
```go
log.Debugf("Hello %s", "boy")
log.Infof("%d is the answer to life, the universe, and everything", 233)
log.Warnf("We are under attack %s!", "boss")
log.Errorf("%s, we have a problem.", "Master Shifu")
log.Fatalf("So Long, and Thanks for All the %s.", "banana")
```
Print a message with the key and value, or `KEYVALS UNPAIRED` if the key and value are not a pair.
```go
log.Debugw("", "Hello", "boy")
log.Infow("", "number", 233)
log.Warnw("", "job", "boss")
log.Errorw("", "name", "Master Shifu")
log.Fatalw("", "fruit", "banana")
```
## Global log
If you are in a project and just want to use a simple log function that can be printed at any time in the global, we provide a global log.
```go
import "github.com/gofiber/fiber/v2/log"
log.Info("info")
log.Warn("warn")
```
The above is using the default `log.DefaultLogger` standard output.
You can also find an already implemented adaptation under contrib, or use your own implemented Logger and use `log.SetLogger` to set the global log logger.
```go
import (
"log"
fiberlog "github.com/gofiber/fiber/v2/log"
)
var _ log.AllLogger = (*customLogger)(nil)
type customLogger struct {
stdlog *log.Logger
}
// ...
// inject your custom logger
fiberlog.SetLogger(customLogger)
```
## Set Level
`log.SetLevel` sets the level of logs below which logs will not be output.
The default logger is LevelTrace.
Note that this method is not **concurrent-safe**.
```go
import "github.com/gofiber/fiber/v2/log"
log.SetLevel(log.LevelInfo)
```
## Set output
`log.SetOutput` sets the output destination of the logger. The default logger types the log in the console.
```go
var logger AllLogger = &defaultLogger{
stdlog: log.New(os.Stderr, "", log.LstdFlags|log.Lshortfile|log.Lmicroseconds),
depth: 4,
}
```
Set the output destination to the file.
```go
// Output to ./test.log file
f, err := os.OpenFile("test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
return
}
log.SetOutput(f)
```
Set the output destination to the console and file.
```go
// Output to ./test.log file
file, _ := os.OpenFile("test.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
iw := io.MultiWriter(os.Stdout, file)
log.SetOutput(iw)
```
## Bind context
Set the context, using the following method will return a `CommonLogger` instance bound to the specified context
```go
commonLogger := log.WithContext(ctx)
commonLogger.Info("info")
```

View file

@ -0,0 +1,9 @@
{
"label": "🧬 Middleware",
"position": 7,
"collapsed": true,
"link": {
"type": "generated-index",
"description": "Middleware is a function chained in the HTTP request cycle with access to the Context which it uses to perform a specific action, for example, logging every request or enabling CORS."
}
}

View file

@ -0,0 +1,169 @@
---
id: adaptor
---
# Adaptor
Converter for net/http handlers to/from Fiber request handlers, special thanks to [@arsmn](https://github.com/arsmn)!
## Signatures
| Name | Signature | Description
| :--- | :--- | :---
| HTTPHandler | `HTTPHandler(h http.Handler) fiber.Handler` | http.Handler -> fiber.Handler
| HTTPHandlerFunc | `HTTPHandlerFunc(h http.HandlerFunc) fiber.Handler` | http.HandlerFunc -> fiber.Handler
| HTTPMiddleware | `HTTPHandlerFunc(mw func(http.Handler) http.Handler) fiber.Handler` | func(http.Handler) http.Handler -> fiber.Handler
| FiberHandler | `FiberHandler(h fiber.Handler) http.Handler` | fiber.Handler -> http.Handler
| FiberHandlerFunc | `FiberHandlerFunc(h fiber.Handler) http.HandlerFunc` | fiber.Handler -> http.HandlerFunc
| FiberApp | `FiberApp(app *fiber.App) http.HandlerFunc` | Fiber app -> http.HandlerFunc
| ConvertRequest | `ConvertRequest(c *fiber.Ctx, forServer bool) (*http.Request, error)` | fiber.Ctx -> http.Request
| CopyContextToFiberContext | `CopyContextToFiberContext(context interface{}, requestContext *fasthttp.RequestCtx)` | context.Context -> fasthttp.RequestCtx
## Examples
### net/http to Fiber
```go
package main
import (
"fmt"
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/adaptor"
)
func main() {
// New fiber app
app := fiber.New()
// http.Handler -> fiber.Handler
app.Get("/", adaptor.HTTPHandler(handler(greet)))
// http.HandlerFunc -> fiber.Handler
app.Get("/func", adaptor.HTTPHandlerFunc(greet))
// Listen on port 3000
app.Listen(":3000")
}
func handler(f http.HandlerFunc) http.Handler {
return http.HandlerFunc(f)
}
func greet(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello World!")
}
```
### net/http middleware to Fiber
```go
package main
import (
"log"
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/adaptor"
)
func main() {
// New fiber app
app := fiber.New()
// http middleware -> fiber.Handler
app.Use(adaptor.HTTPMiddleware(logMiddleware))
// Listen on port 3000
app.Listen(":3000")
}
func logMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("log middleware")
next.ServeHTTP(w, r)
})
}
```
### Fiber Handler to net/http
```go
package main
import (
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/adaptor"
)
func main() {
// fiber.Handler -> http.Handler
http.Handle("/", adaptor.FiberHandler(greet))
// fiber.Handler -> http.HandlerFunc
http.HandleFunc("/func", adaptor.FiberHandlerFunc(greet))
// Listen on port 3000
http.ListenAndServe(":3000", nil)
}
func greet(c *fiber.Ctx) error {
return c.SendString("Hello World!")
}
```
### Fiber App to net/http
```go
package main
import (
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/adaptor"
)
func main() {
app := fiber.New()
app.Get("/greet", greet)
// Listen on port 3000
http.ListenAndServe(":3000", adaptor.FiberApp(app))
}
func greet(c *fiber.Ctx) error {
return c.SendString("Hello World!")
}
```
### Fiber Context to (net/http).Request
```go
package main
import (
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/adaptor"
)
func main() {
app := fiber.New()
app.Get("/greet", greetWithHTTPReq)
// Listen on port 3000
http.ListenAndServe(":3000", adaptor.FiberApp(app))
}
func greetWithHTTPReq(c *fiber.Ctx) error {
httpReq, err := adaptor.ConvertRequest(c, false)
if err != nil {
return err
}
return c.SendString("Request URL: " + httpReq.URL.String())
}
```

View file

@ -0,0 +1,85 @@
---
id: basicauth
---
# BasicAuth
Basic Authentication middleware for [Fiber](https://github.com/gofiber/fiber) that provides an HTTP basic authentication. It calls the next handler for valid credentials and [401 Unauthorized](https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/401) or a custom response for missing or invalid credentials.
## Signatures
```go
func New(config Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/basicauth"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Provide a minimal config
app.Use(basicauth.New(basicauth.Config{
Users: map[string]string{
"john": "doe",
"admin": "123456",
},
}))
// Or extend your config for customization
app.Use(basicauth.New(basicauth.Config{
Users: map[string]string{
"john": "doe",
"admin": "123456",
},
Realm: "Forbidden",
Authorizer: func(user, pass string) bool {
if user == "john" && pass == "doe" {
return true
}
if user == "admin" && pass == "123456" {
return true
}
return false
},
Unauthorized: func(c *fiber.Ctx) error {
return c.SendFile("./unauthorized.html")
},
ContextUsername: "_user",
ContextPassword: "_pass",
}))
```
## Config
| Property | Type | Description | Default |
|:----------------|:----------------------------|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Users | `map[string]string` | Users defines the allowed credentials. | `map[string]string{}` |
| Realm | `string` | Realm is a string to define the realm attribute of BasicAuth. The realm identifies the system to authenticate against and can be used by clients to save credentials. | `"Restricted"` |
| Authorizer | `func(string, string) bool` | Authorizer defines a function to check the credentials. It will be called with a username and password and is expected to return true or false to indicate approval. | `nil` |
| Unauthorized | `fiber.Handler` | Unauthorized defines the response body for unauthorized responses. | `nil` |
| ContextUsername | `interface{}` | ContextUsername is the key to store the username in Locals. | `"username"` |
| ContextPassword | `interface{}` | ContextPassword is the key to store the password in Locals. | `"password"` |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
Users: map[string]string{},
Realm: "Restricted",
Authorizer: nil,
Unauthorized: nil,
ContextUsername: "username",
ContextPassword: "password",
}
```

View file

@ -0,0 +1,99 @@
---
id: cache
---
# Cache
Cache middleware for [Fiber](https://github.com/gofiber/fiber) designed to intercept responses and cache them. This middleware will cache the `Body`, `Content-Type` and `StatusCode` using the `c.Path()` as unique identifier. Special thanks to [@codemicro](https://github.com/codemicro/fiber-cache) for creating this middleware for Fiber core!
Request Directives<br />
`Cache-Control: no-cache` will return the up-to-date response but still caches it. You will always get a `miss` cache status.<br />
`Cache-Control: no-store` will refrain from caching. You will always get the up-to-date response.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cache"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(cache.New())
// Or extend your config for customization
app.Use(cache.New(cache.Config{
Next: func(c *fiber.Ctx) bool {
return c.Query("noCache") == "true"
},
Expiration: 30 * time.Minute,
CacheControl: true,
}))
```
Or you can custom key and expire time like this:
```go
app.Use(cache.New(cache.Config{
ExpirationGenerator: func(c *fiber.Ctx, cfg *cache.Config) time.Duration {
newCacheTime, _ := strconv.Atoi(c.GetRespHeader("Cache-Time", "600"))
return time.Second * time.Duration(newCacheTime)
},
KeyGenerator: func(c *fiber.Ctx) string {
return utils.CopyString(c.Path())
},
}))
app.Get("/", func(c *fiber.Ctx) error {
c.Response().Header.Add("Cache-Time", "6000")
return c.SendString("hi")
})
```
## Config
| Property | Type | Description | Default |
|:---------------------|:------------------------------------------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function that is executed before creating the cache entry and can be used to execute the request without cache creation. If an entry already exists, it will be used. If you want to completely bypass the cache functionality in certain cases, you should use the [skip middleware](./skip.md). | `nil` |
| Expiration | `time.Duration` | Expiration is the time that a cached response will live. | `1 * time.Minute` |
| CacheHeader | `string` | CacheHeader is the header on the response header that indicates the cache status, with the possible return values "hit," "miss," or "unreachable." | `X-Cache` |
| CacheControl | `bool` | CacheControl enables client-side caching if set to true. | `false` |
| KeyGenerator | `func(*fiber.Ctx) string` | Key allows you to generate custom keys. | `func(c *fiber.Ctx) string { return utils.CopyString(c.Path()) }` |
| ExpirationGenerator | `func(*fiber.Ctx, *cache.Config) time.Duration` | ExpirationGenerator allows you to generate custom expiration keys based on the request. | `nil` |
| Storage | `fiber.Storage` | Store is used to store the state of the middleware. | In-memory store |
| Store (Deprecated) | `fiber.Storage` | Deprecated: Use Storage instead. | In-memory store |
| Key (Deprecated) | `func(*fiber.Ctx) string` | Deprecated: Use KeyGenerator instead. | `nil` |
| StoreResponseHeaders | `bool` | StoreResponseHeaders allows you to store additional headers generated by next middlewares & handler. | `false` |
| MaxBytes | `uint` | MaxBytes is the maximum number of bytes of response bodies simultaneously stored in cache. | `0` (No limit) |
| Methods | `[]string` | Methods specifies the HTTP methods to cache. | `[]string{fiber.MethodGet, fiber.MethodHead}` |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
Expiration: 1 * time.Minute,
CacheHeader: "X-Cache",
CacheControl: false,
KeyGenerator: func(c *fiber.Ctx) string {
return utils.CopyString(c.Path())
},
ExpirationGenerator: nil,
StoreResponseHeaders: false,
Storage: nil,
MaxBytes: 0,
Methods: []string{fiber.MethodGet, fiber.MethodHead},
}
```

View file

@ -0,0 +1,85 @@
---
id: compress
---
# Compress
Compression middleware for [Fiber](https://github.com/gofiber/fiber) that will compress the response using `gzip`, `deflate` and `brotli` compression depending on the [Accept-Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Encoding) header.
:::note
The compression middleware refrains from compressing bodies that are smaller than 200 bytes. This decision is based on the observation that, in such cases, the compressed size is likely to exceed the original size, making compression inefficient. [more](https://github.com/valyala/fasthttp/blob/497922a21ef4b314f393887e9c6147b8c3e3eda4/http.go#L1713-L1715)
:::
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/compress"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(compress.New())
// Or extend your config for customization
app.Use(compress.New(compress.Config{
Level: compress.LevelBestSpeed, // 1
}))
// Skip middleware for specific routes
app.Use(compress.New(compress.Config{
Next: func(c *fiber.Ctx) bool {
return c.Path() == "/dont_compress"
},
Level: compress.LevelBestSpeed, // 1
}))
```
## Config
### Config
| Property | Type | Description | Default |
|:---------|:------------------------|:--------------------------------------------------------------------|:-------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Level | `Level` | Level determines the compression algorithm. | `LevelDefault (0)` |
Possible values for the "Level" field are:
- `LevelDisabled (-1)`: Compression is disabled.
- `LevelDefault (0)`: Default compression level.
- `LevelBestSpeed (1)`: Best compression speed.
- `LevelBestCompression (2)`: Best compression.
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
Level: LevelDefault,
}
```
## Constants
```go
// Compression levels
const (
LevelDisabled = -1
LevelDefault = 0
LevelBestSpeed = 1
LevelBestCompression = 2
)
```

214
docs/api/middleware/cors.md Normal file
View file

@ -0,0 +1,214 @@
---
id: cors
---
# CORS
CORS (Cross-Origin Resource Sharing) is a middleware for [Fiber](https://github.com/gofiber/fiber) that allows servers to specify who can access its resources and how. It's not a security feature, but a way to relax the security model of web browsers for cross-origin requests. You can learn more about CORS on [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS).
This middleware works by adding CORS headers to responses from your Fiber application. These headers specify which origins, methods, and headers are allowed for cross-origin requests. It also handles preflight requests, which are a CORS mechanism to check if the actual request is safe to send.
The middleware uses the `AllowOrigins` option to control which origins can make cross-origin requests. It supports single origin, multiple origins, subdomain matching, and wildcard origin. It also allows programmatic origin validation with the `AllowOriginsFunc` option.
To ensure that the provided `AllowOrigins` origins are correctly formatted, this middleware validates and normalizes them. It checks for valid schemes, i.e., HTTP or HTTPS, and it will automatically remove trailing slashes. If the provided origin is invalid, the middleware will panic.
When configuring CORS, it's important to avoid [common pitfalls](#common-pitfalls) like using a wildcard origin with credentials, being overly permissive with origins, and inadequate validation with `AllowOriginsFunc`. Misconfiguration can expose your application to various security risks.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
)
```
After you initiate your Fiber app, you can use the following possibilities:
### Basic usage
To use the default configuration, simply use `cors.New()`. This will allow wildcard origins '*', all methods, no credentials, and no headers or exposed headers.
```go
app.Use(cors.New())
```
### Custom configuration (specific origins, headers, etc.)
```go
// Initialize default config
app.Use(cors.New())
// Or extend your config for customization
app.Use(cors.New(cors.Config{
AllowOrigins: "https://gofiber.io, https://gofiber.net",
AllowHeaders: "Origin, Content-Type, Accept",
}))
```
### Dynamic origin validation
You can use `AllowOriginsFunc` to programmatically determine whether to allow a request based on its origin. This is useful when you need to validate origins against a database or other dynamic sources. The function should return `true` if the origin is allowed, and `false` otherwise.
Be sure to review the [security considerations](#security-considerations) when using `AllowOriginsFunc`.
:::caution
Never allow `AllowOriginsFunc` to return `true` for all origins. This is particularly crucial when `AllowCredentials` is set to `true`. Doing so can bypass the restriction of using a wildcard origin with credentials, exposing your application to serious security threats.
If you need to allow wildcard origins, use `AllowOrigins` with a wildcard `"*"` instead of `AllowOriginsFunc`.
:::
```go
// dbCheckOrigin checks if the origin is in the list of allowed origins in the database.
func dbCheckOrigin(db *sql.DB, origin string) bool {
// Placeholder query - adjust according to your database schema and query needs
query := "SELECT COUNT(*) FROM allowed_origins WHERE origin = $1"
var count int
err := db.QueryRow(query, origin).Scan(&count)
if err != nil {
// Handle error (e.g., log it); for simplicity, we return false here
return false
}
return count > 0
}
// ...
app.Use(cors.New(cors.Config{
AllowOriginsFunc: func(origin string) bool {
return dbCheckOrigin(db, origin)
},
}))
```
### Prohibited usage
The following example is prohibited because it can expose your application to security risks. It sets `AllowOrigins` to `"*"` (a wildcard) and `AllowCredentials` to `true`.
```go
app.Use(cors.New(cors.Config{
AllowOrigins: "*",
AllowCredentials: true,
}))
```
This will result in the following panic:
```
panic: [CORS] 'AllowCredentials' is true, but 'AllowOrigins' cannot be set to `"*"`.
```
## Config
| Property | Type | Description | Default |
|:-----------------|:---------------------------|:-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| AllowOriginsFunc | `func(origin string) bool` | `AllowOriginsFunc` is a function that dynamically determines whether to allow a request based on its origin. If this function returns `true`, the 'Access-Control-Allow-Origin' response header will be set to the request's 'origin' header. This function is only used if the request's origin doesn't match any origin in `AllowOrigins`. | `nil` |
| AllowOrigins | `string` | AllowOrigins defines a comma separated list of origins that may access the resource. This supports subdomain matching, so you can use a value like "https://*.example.com" to allow any subdomain of example.com to submit requests. | `"*"` |
| AllowMethods | `string` | AllowMethods defines a list of methods allowed when accessing the resource. This is used in response to a preflight request. | `"GET,POST,HEAD,PUT,DELETE,PATCH"` |
| AllowHeaders | `string` | AllowHeaders defines a list of request headers that can be used when making the actual request. This is in response to a preflight request. | `""` |
| AllowCredentials | `bool` | AllowCredentials indicates whether or not the response to the request can be exposed when the credentials flag is true. When used as part of a response to a preflight request, this indicates whether or not the actual request can be made using credentials. Note: If true, AllowOrigins cannot be set to a wildcard (`"*"`) to prevent security vulnerabilities. | `false` |
| ExposeHeaders | `string` | ExposeHeaders defines whitelist headers that clients are allowed to access. | `""` |
| MaxAge | `int` | MaxAge indicates how long (in seconds) the results of a preflight request can be cached. If you pass MaxAge 0, the Access-Control-Max-Age header will not be added and the browser will use 5 seconds by default. To disable caching completely, pass MaxAge value negative. It will set the Access-Control-Max-Age header to 0. | `0` |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
AllowOriginsFunc: nil,
AllowOrigins: "*",
AllowMethods: strings.Join([]string{
fiber.MethodGet,
fiber.MethodPost,
fiber.MethodHead,
fiber.MethodPut,
fiber.MethodDelete,
fiber.MethodPatch,
}, ","),
AllowHeaders: "",
AllowCredentials: false,
ExposeHeaders: "",
MaxAge: 0,
}
```
## Subdomain Matching
The `AllowOrigins` configuration supports matching subdomains at any level. This means you can use a value like `"https://*.example.com"` to allow any subdomain of `example.com` to submit requests, including multiple subdomain levels such as `"https://sub.sub.example.com"`.
### Example
If you want to allow CORS requests from any subdomain of `example.com`, including nested subdomains, you can configure the `AllowOrigins` like so:
```go
app.Use(cors.New(cors.Config{
AllowOrigins: "https://*.example.com",
}))
```
# How It Works
The CORS middleware works by adding the necessary CORS headers to responses from your Fiber application. These headers tell browsers what origins, methods, and headers are allowed for cross-origin requests.
When a request comes in, the middleware first checks if it's a preflight request, which is a CORS mechanism to determine whether the actual request is safe to send. Preflight requests are HTTP OPTIONS requests with specific CORS headers. If it's a preflight request, the middleware responds with the appropriate CORS headers and ends the request.
If it's not a preflight request, the middleware adds the CORS headers to the response and passes the request to the next handler. The actual CORS headers added depend on the configuration of the middleware.
The `AllowOrigins` option controls which origins can make cross-origin requests. The middleware handles different `AllowOrigins` configurations as follows:
- **Single origin:** If `AllowOrigins` is set to a single origin like `"http://www.example.com"`, and that origin matches the origin of the incoming request, the middleware adds the header `Access-Control-Allow-Origin: http://www.example.com` to the response.
- **Multiple origins:** If `AllowOrigins` is set to multiple origins like `"https://example.com, https://www.example.com"`, the middleware picks the origin that matches the origin of the incoming request.
- **Subdomain matching:** If `AllowOrigins` includes `"https://*.example.com"`, a subdomain like `https://sub.example.com` will be matched and `"https://sub.example.com"` will be the header. This will also match `https://sub.sub.example.com` and so on, but not `https://example.com`.
- **Wildcard origin:** If `AllowOrigins` is set to `"*"`, the middleware uses that and adds the header `Access-Control-Allow-Origin: *` to the response.
In all cases above, except the **Wildcard origin**, the middleware will either add the `Access-Control-Allow-Origin` header to the response matching the origin of the incoming request, or it will not add the header at all if the origin is not allowed.
- **Programmatic origin validation:**: The middleware also handles the `AllowOriginsFunc` option, which allows you to programmatically determine if an origin is allowed. If `AllowOriginsFunc` returns `true` for an origin, the middleware sets the `Access-Control-Allow-Origin` header to that origin.
The `AllowMethods` option controls which HTTP methods are allowed. For example, if `AllowMethods` is set to `"GET, POST"`, the middleware adds the header `Access-Control-Allow-Methods: GET, POST` to the response.
The `AllowHeaders` option specifies which headers are allowed in the actual request. The middleware sets the Access-Control-Allow-Headers response header to the value of `AllowHeaders`. This informs the client which headers it can use in the actual request.
The `AllowCredentials` option indicates whether the response to the request can be exposed when the credentials flag is true. If `AllowCredentials` is set to `true`, the middleware adds the header `Access-Control-Allow-Credentials: true` to the response. To prevent security vulnerabilities, `AllowCredentials` cannot be set to `true` if `AllowOrigins` is set to a wildcard (`*`).
The `ExposeHeaders` option defines a whitelist of headers that clients are allowed to access. If `ExposeHeaders` is set to `"X-Custom-Header"`, the middleware adds the header `Access-Control-Expose-Headers: X-Custom-Header` to the response.
The `MaxAge` option indicates how long the results of a preflight request can be cached. If `MaxAge` is set to `3600`, the middleware adds the header `Access-Control-Max-Age: 3600` to the response.
The `Vary` header is used in this middleware to inform the client that the server's response to a request. For or both preflight and actual requests, the Vary header is set to `Access-Control-Request-Method` and `Access-Control-Request-Headers`. For preflight requests, the Vary header is also set to `Origin`. The `Vary` header is important for caching. It helps caches (like a web browser's cache or a CDN) determine when a cached response can be used in response to a future request, and when the server needs to be queried for a new response.
## Security Considerations
When configuring CORS, misconfiguration can potentially expose your application to various security risks. Here are some secure configurations and common pitfalls to avoid:
### Secure Configurations
- **Specify Allowed Origins**: Instead of using a wildcard (`"*"`), specify the exact domains allowed to make requests. For example, `AllowOrigins: "https://www.example.com, https://api.example.com"` ensures only these domains can make cross-origin requests to your application.
- **Use Credentials Carefully**: If your application needs to support credentials in cross-origin requests, ensure `AllowCredentials` is set to `true` and specify exact origins in `AllowOrigins`. Do not use a wildcard origin in this case.
- **Limit Exposed Headers**: Only whitelist headers that are necessary for the client-side application by setting `ExposeHeaders` appropriately. This minimizes the risk of exposing sensitive information.
### Common Pitfalls
- **Wildcard Origin with Credentials**: Setting `AllowOrigins` to `"*"` (a wildcard) and `AllowCredentials` to `true` is a common misconfiguration. This combination is prohibited because it can expose your application to security risks.
- **Overly Permissive Origins**: Specifying too many origins or using overly broad patterns (e.g., `https://*.example.com`) can inadvertently allow malicious sites to interact with your application. Be as specific as possible with allowed origins.
- **Inadequate `AllowOriginsFunc` Validation**: When using `AllowOriginsFunc` for dynamic origin validation, ensure the function includes robust checks to prevent unauthorized origins from being accepted. Overly permissive validation can lead to security vulnerabilities. Never allow `AllowOriginsFunc` to return `true` for all origins. This is particularly crucial when `AllowCredentials` is set to `true`. Doing so can bypass the restriction of using a wildcard origin with credentials, exposing your application to serious security threats. If you need to allow wildcard origins, use `AllowOrigins` with a wildcard `"*"` instead of `AllowOriginsFunc`.
Remember, the key to secure CORS configuration is specificity and caution. By carefully selecting which origins, methods, and headers are allowed, you can help protect your application from cross-origin attacks.

256
docs/api/middleware/csrf.md Normal file
View file

@ -0,0 +1,256 @@
---
id: csrf
---
# CSRF
The CSRF middleware for [Fiber](https://github.com/gofiber/fiber) provides protection against [Cross-Site Request Forgery](https://en.wikipedia.org/wiki/Cross-site_request_forgery) (CSRF) attacks. Requests made using methods other than those defined as 'safe' by [RFC9110#section-9.2.1](https://datatracker.ietf.org/doc/html/rfc9110.html#section-9.2.1) (GET, HEAD, OPTIONS, and TRACE) are validated using tokens. If a potential attack is detected, the middleware will return a default 403 Forbidden error.
This middleware offers two [Token Validation Patterns](#token-validation-patterns): the [Double Submit Cookie Pattern (default)](#double-submit-cookie-pattern-default), and the [Synchronizer Token Pattern (with Session)](#synchronizer-token-pattern-with-session).
As a [Defense In Depth](#defense-in-depth) measure, this middleware performs [Referer Checking](#referer-checking) for HTTPS requests.
## Token Generation
CSRF tokens are generated on 'safe' requests and when the existing token has expired or hasn't been set yet. If `SingleUseToken` is `true`, a new token is generated after each use. Retrieve the CSRF token using `c.Locals(contextKey)`, where `contextKey` is defined within the configuration.
## Security Considerations
This middleware is designed to protect against CSRF attacks but does not protect against other attack vectors, such as XSS. It should be used in combination with other security measures.
:::danger
Never use 'safe' methods to mutate data, for example, never use a GET request to modify a resource. This middleware will not protect against CSRF attacks on 'safe' methods.
:::
### Token Validation Patterns
#### Double Submit Cookie Pattern (Default)
By default, the middleware generates and stores tokens using the `fiber.Storage` interface. These tokens are not linked to any particular user session, and they are validated using the Double Submit Cookie pattern. The token is stored in a cookie, and then sent as a header on requests. The middleware compares the cookie value with the header value to validate the token. This is a secure pattern that does not require a user session.
When the authorization status changes, the previously issued token MUST be deleted, and a new one generated. See [Token Lifecycle](#token-lifecycle) [Deleting Tokens](#deleting-tokens) for more information.
:::caution
When using this pattern, it's important to set the `CookieSameSite` option to `Lax` or `Strict` and ensure that the Extractor is not `CsrfFromCookie`, and KeyLookup is not `cookie:<name>`.
:::
:::note
When using this pattern, this middleware uses our [Storage](https://github.com/gofiber/storage) package to support various databases through a single interface. The default configuration for Storage saves data to memory. See [Custom Storage/Database](#custom-storagedatabase) for customizing the storage.
:::
#### Synchronizer Token Pattern (with Session)
When using this middleware with a user session, the middleware can be configured to store the token within the session. This method is recommended when using a user session, as it is generally more secure than the Double Submit Cookie Pattern.
When using this pattern it's important to regenerate the session when the authorization status changes, this will also delete the token. See: [Token Lifecycle](#token-lifecycle) for more information.
:::caution
Pre-sessions are required and will be created automatically if not present. Use a session value to indicate authentication instead of relying on presence of a session.
:::
### Defense In Depth
When using this middleware, it's recommended to serve your pages over HTTPS, set the `CookieSecure` option to `true`, and set the `CookieSameSite` option to `Lax` or `Strict`. This ensures that the cookie is only sent over HTTPS and not on requests from external sites.
:::note
Cookie prefixes `__Host-` and `__Secure-` can be used to further secure the cookie. Note that these prefixes are not supported by all browsers and there are other limitations. See [MDN#Set-Cookie#cookie_prefixes](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie#cookie_prefixes) for more information.
To use these prefixes, set the `CookieName` option to `__Host-csrf_` or `__Secure-csrf_`.
:::
### Referer Checking
For HTTPS requests, this middleware performs strict referer checking. Even if a subdomain can set or modify cookies on your domain, it can't force a user to post to your application since that request won't come from your own exact domain.
:::caution
When HTTPS requests are protected by CSRF, referer checking is always carried out.
The Referer header is automatically included in requests by all modern browsers, including those made using the JS Fetch API. However, if you're making use of this middleware with a custom client, it's important to ensure that the client sends a valid Referer header.
:::
### Token Lifecycle
Tokens are valid until they expire or until they are deleted. By default, tokens are valid for 1 hour, and each subsequent request extends the expiration by 1 hour. The token only expires if the user doesn't make a request for the duration of the expiration time.
#### Token Reuse
By default, tokens may be used multiple times. If you want to delete the token after it has been used, you can set the `SingleUseToken` option to `true`. This will delete the token after it has been used, and a new token will be generated on the next request.
:::info
Using `SingleUseToken` comes with usability trade-offs and is not enabled by default. For example, it can interfere with the user experience if the user has multiple tabs open or uses the back button.
:::
#### Deleting Tokens
When the authorization status changes, the CSRF token MUST be deleted, and a new one generated. This can be done by calling `handler.DeleteToken(c)`.
```go
if handler, ok := app.AcquireCtx(ctx).Locals(csrf.ConfigDefault.HandlerContextKey).(*CSRFHandler); ok {
if err := handler.DeleteToken(app.AcquireCtx(ctx)); err != nil {
// handle error
}
}
```
:::tip
If you are using this middleware with the fiber session middleware, then you can simply call `session.Destroy()`, `session.Regenerate()`, or `session.Reset()` to delete session and the token stored therein.
:::
### BREACH
It's important to note that the token is sent as a header on every request. If you include the token in a page that is vulnerable to [BREACH](https://en.wikipedia.org/wiki/BREACH), an attacker may be able to extract the token. To mitigate this, ensure your pages are served over HTTPS, disable HTTP compression, and implement rate limiting for requests.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework:
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/csrf"
)
```
After initializing your Fiber app, you can use the following code to initialize the middleware:
```go
// Initialize default config
app.Use(csrf.New())
// Or extend your config for customization
app.Use(csrf.New(csrf.Config{
KeyLookup: "header:X-Csrf-Token",
CookieName: "csrf_",
CookieSameSite: "Lax",
Expiration: 1 * time.Hour,
KeyGenerator: utils.UUIDv4,
}))
```
## Config
| Property | Type | Description | Default |
|:------------------|:-----------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:-----------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| KeyLookup | `string` | KeyLookup is a string in the form of "`<source>:<key>`" that is used to create an Extractor that extracts the token from the request. Possible values: "`header:<name>`", "`query:<name>`", "`param:<name>`", "`form:<name>`", "`cookie:<name>`". Ignored if an Extractor is explicitly set. | "header:X-Csrf-Token" |
| CookieName | `string` | Name of the csrf cookie. This cookie will store the csrf key. | "csrf_" |
| CookieDomain | `string` | Domain of the CSRF cookie. | "" |
| CookiePath | `string` | Path of the CSRF cookie. | "" |
| CookieSecure | `bool` | Indicates if the CSRF cookie is secure. | false |
| CookieHTTPOnly | `bool` | Indicates if the CSRF cookie is HTTP-only. | false |
| CookieSameSite | `string` | Value of SameSite cookie. | "Lax" |
| CookieSessionOnly | `bool` | Decides whether the cookie should last for only the browser session. Ignores Expiration if set to true. | false |
| Expiration | `time.Duration` | Expiration is the duration before the CSRF token will expire. | 1 * time.Hour |
| SingleUseToken | `bool` | SingleUseToken indicates if the CSRF token be destroyed and a new one generated on each use. (See TokenLifecycle) | false |
| Storage | `fiber.Storage` | Store is used to store the state of the middleware. | `nil` |
| Session | `*session.Store` | Session is used to store the state of the middleware. Overrides Storage if set. | `nil` |
| SessionKey | `string` | SessionKey is the key used to store the token within the session. | "fiber.csrf.token" |
| ContextKey | `inteface{}` | Context key to store the generated CSRF token into the context. If left empty, the token will not be stored within the context. | "" |
| KeyGenerator | `func() string` | KeyGenerator creates a new CSRF token. | utils.UUID |
| CookieExpires | `time.Duration` (Deprecated) | Deprecated: Please use Expiration. | 0 |
| Cookie | `*fiber.Cookie` (Deprecated) | Deprecated: Please use Cookie* related fields. | `nil` |
| TokenLookup | `string` (Deprecated) | Deprecated: Please use KeyLookup. | "" |
| ErrorHandler | `fiber.ErrorHandler` | ErrorHandler is executed when an error is returned from fiber.Handler. | DefaultErrorHandler |
| Extractor | `func(*fiber.Ctx) (string, error)` | Extractor returns the CSRF token. If set, this will be used in place of an Extractor based on KeyLookup. | Extractor based on KeyLookup |
| HandlerContextKey | `interface{}` | HandlerContextKey is used to store the CSRF Handler into context. | "fiber.csrf.handler" |
### Default Config
```go
var ConfigDefault = Config{
KeyLookup: "header:" + HeaderName,
CookieName: "csrf_",
CookieSameSite: "Lax",
Expiration: 1 * time.Hour,
KeyGenerator: utils.UUIDv4,
ErrorHandler: defaultErrorHandler,
Extractor: CsrfFromHeader(HeaderName),
SessionKey: "fiber.csrf.token",
HandlerContextKey: "fiber.csrf.handler",
}
```
### Recommended Config (with session)
It's recommended to use this middleware with [fiber/middleware/session](https://docs.gofiber.io/api/middleware/session) to store the CSRF token within the session. This is generally more secure than the default configuration.
```go
var ConfigDefault = Config{
KeyLookup: "header:" + HeaderName,
CookieName: "__Host-csrf_",
CookieSameSite: "Lax",
CookieSecure: true,
CookieSessionOnly: true,
CookieHTTPOnly: true,
Expiration: 1 * time.Hour,
KeyGenerator: utils.UUIDv4,
ErrorHandler: defaultErrorHandler,
Extractor: CsrfFromHeader(HeaderName),
Session: session.Store,
SessionKey: "fiber.csrf.token",
HandlerContextKey: "fiber.csrf.handler",
}
```
## Constants
```go
const (
HeaderName = "X-Csrf-Token"
)
```
## Sentinel Errors
The CSRF middleware utilizes a set of sentinel errors to handle various scenarios and communicate errors effectively. These can be used within a [custom error handler](#custom-error-handler) to handle errors returned by the middleware.
### Errors Returned to Error Handler
- `ErrTokenNotFound`: Indicates that the CSRF token was not found.
- `ErrTokenInvalid`: Indicates that the CSRF token is invalid.
- `ErrNoReferer`: Indicates that the referer was not supplied.
- `ErrBadReferer`: Indicates that the referer is invalid.
If you use the default error handler, the client will receive a 403 Forbidden error without any additional information.
## Custom Error Handler
You can use a custom error handler to handle errors returned by the CSRF middleware. The error handler is executed when an error is returned from the middleware. The error handler is passed the error returned from the middleware and the fiber.Ctx.
Example, returning a JSON response for API requests and rendering an error page for other requests:
```go
app.Use(csrf.New(csrf.Config{
ErrorHandler: func(c *fiber.Ctx, err error) error {
accepts := c.Accepts("html", "json")
path := c.Path()
if accepts == "json" || strings.HasPrefix(path, "/api/") {
return c.Status(fiber.StatusForbidden).JSON(fiber.Map{
"error": "Forbidden",
})
}
return c.Status(fiber.StatusForbidden).Render("error", fiber.Map{
"Title": "Forbidden",
"Status": fiber.StatusForbidden,
}, "layouts/main")
},
}))
```
## Custom Storage/Database
You can use any storage from our [storage](https://github.com/gofiber/storage/) package.
```go
storage := sqlite3.New() // From github.com/gofiber/storage/sqlite3
app.Use(csrf.New(csrf.Config{
Storage: storage,
}))
```

View file

@ -0,0 +1,82 @@
---
id: earlydata
---
# EarlyData
The Early Data middleware for [Fiber](https://github.com/gofiber/fiber) adds support for TLS 1.3's early data ("0-RTT") feature.
Citing [RFC 8446](https://datatracker.ietf.org/doc/html/rfc8446#section-2-3), when a client and server share a PSK, TLS 1.3 allows clients to send data on the first flight ("early data") to speed up the request, effectively reducing the regular 1-RTT request to a 0-RTT request.
Make sure to enable fiber's `EnableTrustedProxyCheck` config option before using this middleware in order to not trust bogus HTTP request headers of the client.
Also be aware that enabling support for early data in your reverse proxy (e.g. nginx, as done with a simple `ssl_early_data on;`) makes requests replayable. Refer to the following documents before continuing:
- https://datatracker.ietf.org/doc/html/rfc8446#section-8
- https://blog.trailofbits.com/2019/03/25/what-application-developers-need-to-know-about-tls-early-data-0rtt/
By default, this middleware allows early data requests on safe HTTP request methods only and rejects the request otherwise, i.e. aborts the request before executing your handler. This behavior can be controlled by the `AllowEarlyData` config option.
Safe HTTP methods — `GET`, `HEAD`, `OPTIONS` and `TRACE` — should not modify a state on the server.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/earlydata"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(earlydata.New())
// Or extend your config for customization
app.Use(earlydata.New(earlydata.Config{
Error: fiber.ErrTooEarly,
// ...
}))
```
## Config
| Property | Type | Description | Default |
|:---------------|:------------------------|:-------------------------------------------------------------------------------------|:-------------------------------------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| IsEarlyData | `func(*fiber.Ctx) bool` | IsEarlyData returns whether the request is an early-data request. | Function checking if "Early-Data" header equals "1" |
| AllowEarlyData | `func(*fiber.Ctx) bool` | AllowEarlyData returns whether the early-data request should be allowed or rejected. | Function rejecting on unsafe and allowing safe methods |
| Error | `error` | Error is returned in case an early-data request is rejected. | `fiber.ErrTooEarly` |
## Default Config
```go
var ConfigDefault = Config{
IsEarlyData: func(c *fiber.Ctx) bool {
return c.Get(DefaultHeaderName) == DefaultHeaderTrueValue
},
AllowEarlyData: func(c *fiber.Ctx) bool {
return fiber.IsMethodSafe(c.Method())
},
Error: fiber.ErrTooEarly,
}
```
## Constants
```go
const (
DefaultHeaderName = "Early-Data"
DefaultHeaderTrueValue = "1"
)
```

View file

@ -0,0 +1,101 @@
---
id: encryptcookie
---
# Encrypt Cookie
Encrypt Cookie is a middleware for [Fiber](https://github.com/gofiber/fiber) that secures your cookie values through encryption.
:::note
This middleware encrypts cookie values and not the cookie names.
:::
## Signatures
```go
// Intitializes the middleware
func New(config ...Config) fiber.Handler
// Returns a random 32 character long string
func GenerateKey() string
```
## Examples
To use the Encrypt Cookie middleware, first, import the middleware package as part of the Fiber web framework:
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/encryptcookie"
)
```
Once you've imported the middleware package, you can use it inside your Fiber app:
```go
// Provide a minimal configuration
app.Use(encryptcookie.New(encryptcookie.Config{
Key: "secret-thirty-2-character-string",
}))
// Retrieve the encrypted cookie value
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("value=" + c.Cookies("test"))
})
// Create an encrypted cookie
app.Post("/", func(c *fiber.Ctx) error {
c.Cookie(&fiber.Cookie{
Name: "test",
Value: "SomeThing",
})
return nil
})
```
:::note
`Key` must be a 32 character string. It's used to encrypt the values, so make sure it is random and keep it secret.
You can run `openssl rand -base64 32` or call `encryptcookie.GenerateKey()` to create a random key for you.
Make sure not to set `Key` to `encryptcookie.GenerateKey()` because that will create a new key every run.
:::
## Config
| Property | Type | Description | Default |
|:----------|:----------------------------------------------------|:------------------------------------------------------------------------------------------------------|:-----------------------------|
| Next | `func(*fiber.Ctx) bool` | A function to skip this middleware when returned true. | `nil` |
| Except | `[]string` | Array of cookie keys that should not be encrypted. | `[]` |
| Key | `string` | A base64-encoded unique key to encode & decode cookies. Required. Key length should be 32 characters. | (No default, required field) |
| Encryptor | `func(decryptedString, key string) (string, error)` | A custom function to encrypt cookies. | `EncryptCookie` |
| Decryptor | `func(encryptedString, key string) (string, error)` | A custom function to decrypt cookies. | `DecryptCookie` |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
Except: []string{},
Key: "",
Encryptor: EncryptCookie,
Decryptor: DecryptCookie,
}
```
## Usage With Other Middlewares That Reads Or Modify Cookies
Place the encryptcookie middleware before any other middleware that reads or modifies cookies. For example, if you are using the CSRF middleware, ensure that the encryptcookie middleware is placed before it. Failure to do so may prevent the CSRF middleware from reading the encrypted cookie.
You may also choose to exclude certain cookies from encryption. For instance, if you are using the CSRF middleware with a frontend framework like Angular, and the framework reads the token from a cookie, you should exclude that cookie from encryption. This can be achieved by adding the cookie name to the Except array in the configuration:
```go
app.Use(encryptcookie.New(encryptcookie.Config{
Key: "secret-thirty-2-character-string",
Except: []string{csrf.ConfigDefault.CookieName}, // exclude CSRF cookie
}))
app.Use(csrf.New(csrf.Config{
KeyLookup: "header:" + csrf.HeaderName,
CookieSameSite: "Lax",
CookieSecure: true,
CookieHTTPOnly: false,
}))
```

View file

@ -0,0 +1,69 @@
---
id: envvar
---
# EnvVar
EnvVar middleware for [Fiber](https://github.com/gofiber/fiber) that can be used to expose environment variables with various options.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/envvar"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use("/expose/envvars", envvar.New())
// Or extend your config for customization
app.Use("/expose/envvars", envvar.New(
envvar.Config{
ExportVars: map[string]string{"testKey": "", "testDefaultKey": "testDefaultVal"},
ExcludeVars: map[string]string{"excludeKey": ""},
}),
)
```
:::note
You will need to provide a path to use the envvar middleware.
:::
## Response
Http response contract:
```
{
"vars": {
"someEnvVariable": "someValue",
"anotherEnvVariable": "anotherValue",
}
}
```
## Config
| Property | Type | Description | Default |
|:------------|:--------------------|:-----------------------------------------------------------------------------|:--------|
| ExportVars | `map[string]string` | ExportVars specifies the environment variables that should be exported. | `nil` |
| ExcludeVars | `map[string]string` | ExcludeVars specifies the environment variables that should not be exported. | `nil` |
## Default Config
```go
Config{}
```

View file

@ -0,0 +1,62 @@
---
id: etag
---
# ETag
ETag middleware for [Fiber](https://github.com/gofiber/fiber) that lets caches be more efficient and save bandwidth, as a web server does not need to resend a full response if the content has not changed.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/etag"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(etag.New())
// Get / receives Etag: "13-1831710635" in response header
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
// Or extend your config for customization
app.Use(etag.New(etag.Config{
Weak: true,
}))
// Get / receives Etag: "W/"13-1831710635" in response header
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
```
## Config
| Property | Type | Description | Default |
|:---------|:------------------------|:-------------------------------------------------------------------------------------------------------------------|:--------|
| Weak | `bool` | Weak indicates that a weak validator is used. Weak etags are easy to generate but are less useful for comparisons. | `false` |
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
Weak: false,
}
```

View file

@ -0,0 +1,72 @@
---
id: expvar
---
# ExpVar
Expvar middleware for [Fiber](https://github.com/gofiber/fiber) that serves via its HTTP server runtime exposed variants in the JSON format. The package is typically only imported for the side effect of registering its HTTP handlers. The handled path is `/debug/vars`.
## Signatures
```go
func New() fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
expvarmw "github.com/gofiber/fiber/v2/middleware/expvar"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
var count = expvar.NewInt("count")
app.Use(expvarmw.New())
app.Get("/", func(c *fiber.Ctx) error {
count.Add(1)
return c.SendString(fmt.Sprintf("hello expvar count %d", count.Value()))
})
```
Visit path `/debug/vars` to see all vars and use query `r=key` to filter exposed variables.
```bash
curl 127.0.0.1:3000
hello expvar count 1
curl 127.0.0.1:3000/debug/vars
{
"cmdline": ["xxx"],
"count": 1,
"expvarHandlerCalls": 33,
"expvarRegexpErrors": 0,
"memstats": {...}
}
curl 127.0.0.1:3000/debug/vars?r=c
{
"cmdline": ["xxx"],
"count": 1
}
```
## Config
| Property | Type | Description | Default |
|:---------|:------------------------|:--------------------------------------------------------------------|:--------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
}
```

View file

@ -0,0 +1,63 @@
---
id: favicon
---
# Favicon
Favicon middleware for [Fiber](https://github.com/gofiber/fiber) that ignores favicon requests or caches a provided icon in memory to improve performance by skipping disk access. User agents request favicon.ico frequently and indiscriminately, so you may wish to exclude these requests from your logs by using this middleware before your logger middleware.
:::note
This middleware is exclusively for serving the default, implicit favicon, which is GET /favicon.ico or [custom favicon URL](#config).
:::
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/favicon"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(favicon.New())
// Or extend your config for customization
app.Use(favicon.New(favicon.Config{
File: "./favicon.ico",
URL: "/favicon.ico",
}))
```
## Config
| Property | Type | Description | Default |
|:-------------|:------------------------|:---------------------------------------------------------------------------------|:---------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Data | `[]byte` | Raw data of the favicon file. This can be used instead of `File`. | `nil` |
| File | `string` | File holds the path to an actual favicon that will be cached. | "" |
| URL | `string` | URL for favicon handler. | "/favicon.ico" |
| FileSystem | `http.FileSystem` | FileSystem is an optional alternate filesystem to search for the favicon in. | `nil` |
| CacheControl | `string` | CacheControl defines how the Cache-Control header in the response should be set. | "public, max-age=31536000" |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
File: "",
URL: fPath,
CacheControl: "public, max-age=31536000",
}
```

View file

@ -0,0 +1,300 @@
---
id: filesystem
---
# FileSystem
Filesystem middleware for [Fiber](https://github.com/gofiber/fiber) that enables you to serve files from a directory.
:::caution
**`:params` & `:optionals?` within the prefix path are not supported!**
**To handle paths with spaces (or other url encoded values) make sure to set `fiber.Config{ UnescapePath: true }`**
:::
## Signatures
```go
func New(config Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Provide a minimal config
app.Use(filesystem.New(filesystem.Config{
Root: http.Dir("./assets"),
}))
// Or extend your config for customization
app.Use(filesystem.New(filesystem.Config{
Root: http.Dir("./assets"),
Browse: true,
Index: "index.html",
NotFoundFile: "404.html",
MaxAge: 3600,
}))
```
> If your environment (Go 1.16+) supports it, we recommend using Go Embed instead of the other solutions listed as this one is native to Go and the easiest to use.
## embed
[Embed](https://golang.org/pkg/embed/) is the native method to embed files in a Golang excecutable. Introduced in Go 1.16.
```go
package main
import (
"embed"
"io/fs"
"log"
"net/http"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
)
// Embed a single file
//go:embed index.html
var f embed.FS
// Embed a directory
//go:embed static/*
var embedDirStatic embed.FS
func main() {
app := fiber.New()
app.Use("/", filesystem.New(filesystem.Config{
Root: http.FS(f),
}))
// Access file "image.png" under `static/` directory via URL: `http://<server>/static/image.png`.
// Without `PathPrefix`, you have to access it via URL:
// `http://<server>/static/static/image.png`.
app.Use("/static", filesystem.New(filesystem.Config{
Root: http.FS(embedDirStatic),
PathPrefix: "static",
Browse: true,
}))
log.Fatal(app.Listen(":3000"))
}
```
## pkger
[https://github.com/markbates/pkger](https://github.com/markbates/pkger)
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
"github.com/markbates/pkger"
)
func main() {
app := fiber.New()
app.Use("/assets", filesystem.New(filesystem.Config{
Root: pkger.Dir("/assets"),
}))
log.Fatal(app.Listen(":3000"))
}
```
## packr
[https://github.com/gobuffalo/packr](https://github.com/gobuffalo/packr)
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
"github.com/gobuffalo/packr/v2"
)
func main() {
app := fiber.New()
app.Use("/assets", filesystem.New(filesystem.Config{
Root: packr.New("Assets Box", "/assets"),
}))
log.Fatal(app.Listen(":3000"))
}
```
## go.rice
[https://github.com/GeertJohan/go.rice](https://github.com/GeertJohan/go.rice)
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
"github.com/GeertJohan/go.rice"
)
func main() {
app := fiber.New()
app.Use("/assets", filesystem.New(filesystem.Config{
Root: rice.MustFindBox("assets").HTTPBox(),
}))
log.Fatal(app.Listen(":3000"))
}
```
## fileb0x
[https://github.com/UnnoTed/fileb0x](https://github.com/UnnoTed/fileb0x)
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
"<Your go module>/myEmbeddedFiles"
)
func main() {
app := fiber.New()
app.Use("/assets", filesystem.New(filesystem.Config{
Root: myEmbeddedFiles.HTTP,
}))
log.Fatal(app.Listen(":3000"))
}
```
## statik
[https://github.com/rakyll/statik](https://github.com/rakyll/statik)
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
// Use blank to invoke init function and register data to statik
_ "<Your go module>/statik"
"github.com/rakyll/statik/fs"
)
func main() {
statikFS, err := fs.New()
if err != nil {
panic(err)
}
app := fiber.New()
app.Use("/", filesystem.New(filesystem.Config{
Root: statikFS,
}))
log.Fatal(app.Listen(":3000"))
}
```
## Config
| Property | Type | Description | Default |
|:-------------------|:------------------------|:------------------------------------------------------------------------------------------------------------|:-------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Root | `http.FileSystem` | Root is a FileSystem that provides access to a collection of files and directories. | `nil` |
| PathPrefix | `string` | PathPrefix defines a prefix to be added to a filepath when reading a file from the FileSystem. | "" |
| Browse | `bool` | Enable directory browsing. | `false` |
| Index | `string` | Index file for serving a directory. | "index.html" |
| MaxAge | `int` | The value for the Cache-Control HTTP-header that is set on the file response. MaxAge is defined in seconds. | 0 |
| NotFoundFile | `string` | File to return if the path is not found. Useful for SPA's. | "" |
| ContentTypeCharset | `string` | The value for the Content-Type HTTP-header that is set on the file response. | "" |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
Root: nil,
PathPrefix: "",
Browse: false,
Index: "/index.html",
MaxAge: 0,
ContentTypeCharset: "",
}
```
## Utils
### SendFile
Serves a file from an [HTTP file system](https://pkg.go.dev/net/http#FileSystem) at the specified path.
```go title="Signature" title="Signature"
func SendFile(c *fiber.Ctx, filesystem http.FileSystem, path string) error
```
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
)
```
```go title="Example"
// Define a route to serve a specific file
app.Get("/download", func(c *fiber.Ctx) error {
// Serve the file using SendFile function
err := filesystem.SendFile(c, http.Dir("your/filesystem/root"), "path/to/your/file.txt")
if err != nil {
// Handle the error, e.g., return a 404 Not Found response
return c.Status(fiber.StatusNotFound).SendString("File not found")
}
return nil
})
```
```go title="Example"
// Serve static files from the "build" directory using Fiber's built-in middleware.
app.Use("/", filesystem.New(filesystem.Config{
Root: http.FS(f), // Specify the root directory for static files.
PathPrefix: "build", // Define the path prefix where static files are served.
}))
// For all other routes (wildcard "*"), serve the "index.html" file from the "build" directory.
app.Use("*", func(ctx *fiber.Ctx) error {
return filesystem.SendFile(ctx, http.FS(f), "build/index.html")
})
```

View file

@ -0,0 +1,106 @@
---
id: healthcheck
---
# Health Check
Liveness and readiness probes middleware for [Fiber](https://github.com/gofiber/fiber) that provides two endpoints for checking the liveness and readiness state of HTTP applications.
## Overview
- **Liveness Probe**: Checks if the server is up and running.
- **Default Endpoint**: `/livez`
- **Behavior**: By default returns `true` immediately when the server is operational.
- **Readiness Probe**: Assesses if the application is ready to handle requests.
- **Default Endpoint**: `/readyz`
- **Behavior**: By default returns `true` immediately when the server is operational.
- **HTTP Status Codes**:
- `200 OK`: Returned when the checker function evaluates to `true`.
- `503 Service Unavailable`: Returned when the checker function evaluates to `false`.
## Signatures
```go
func New(config Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the [Fiber](https://github.com/gofiber/fiber) web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/healthcheck"
)
```
After you initiate your [Fiber](https://github.com/gofiber/fiber) app, you can use the following possibilities:
```go
// Provide a minimal config
app.Use(healthcheck.New())
// Or extend your config for customization
app.Use(healthcheck.New(healthcheck.Config{
LivenessProbe: func(c *fiber.Ctx) bool {
return true
},
LivenessEndpoint: "/live",
ReadinessProbe: func(c *fiber.Ctx) bool {
return serviceA.Ready() && serviceB.Ready() && ...
},
ReadinessEndpoint: "/ready",
}))
```
## Config
```go
type Config struct {
// Next defines a function to skip this middleware when returned true.
//
// Optional. Default: nil
Next func(c *fiber.Ctx) bool
// Function used for checking the liveness of the application. Returns true if the application
// is running and false if it is not. The liveness probe is typically used to indicate if
// the application is in a state where it can handle requests (e.g., the server is up and running).
//
// Optional. Default: func(c *fiber.Ctx) bool { return true }
LivenessProbe HealthChecker
// HTTP endpoint at which the liveness probe will be available.
//
// Optional. Default: "/livez"
LivenessEndpoint string
// Function used for checking the readiness of the application. Returns true if the application
// is ready to process requests and false otherwise. The readiness probe typically checks if all necessary
// services, databases, and other dependencies are available for the application to function correctly.
//
// Optional. Default: func(c *fiber.Ctx) bool { return true }
ReadinessProbe HealthChecker
// HTTP endpoint at which the readiness probe will be available.
// Optional. Default: "/readyz"
ReadinessEndpoint string
}
```
## Default Config
The default configuration used by this middleware is defined as follows:
```go
func defaultLivenessProbe(*fiber.Ctx) bool { return true }
func defaultReadinessProbe(*fiber.Ctx) bool { return true }
var ConfigDefault = Config{
LivenessProbe: defaultLivenessProbe,
ReadinessProbe: defaultReadinessProbe,
LivenessEndpoint: "/livez",
ReadinessEndpoint: "/readyz",
}
```

View file

@ -0,0 +1,82 @@
---
id: helmet
---
# Helmet
Helmet middleware helps secure your apps by setting various HTTP headers.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/helmet"
)
func main() {
app := fiber.New()
app.Use(helmet.New())
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Welcome!")
})
app.Listen(":3000")
}
```
**Test:**
```curl
curl -I http://localhost:3000
```
## Config
| Property | Type | Description | Default |
|:--------------------------|:------------------------|:--------------------------------------------|:-----------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip middleware. | `nil` |
| XSSProtection | `string` | XSSProtection | "0" |
| ContentTypeNosniff | `string` | ContentTypeNosniff | "nosniff" |
| XFrameOptions | `string` | XFrameOptions | "SAMEORIGIN" |
| HSTSMaxAge | `int` | HSTSMaxAge | 0 |
| HSTSExcludeSubdomains | `bool` | HSTSExcludeSubdomains | false |
| ContentSecurityPolicy | `string` | ContentSecurityPolicy | "" |
| CSPReportOnly | `bool` | CSPReportOnly | false |
| HSTSPreloadEnabled | `bool` | HSTSPreloadEnabled | false |
| ReferrerPolicy | `string` | ReferrerPolicy | "ReferrerPolicy" |
| PermissionPolicy | `string` | Permissions-Policy | "" |
| CrossOriginEmbedderPolicy | `string` | Cross-Origin-Embedder-Policy | "require-corp" |
| CrossOriginOpenerPolicy | `string` | Cross-Origin-Opener-Policy | "same-origin" |
| CrossOriginResourcePolicy | `string` | Cross-Origin-Resource-Policy | "same-origin" |
| OriginAgentCluster | `string` | Origin-Agent-Cluster | "?1" |
| XDNSPrefetchControl | `string` | X-DNS-Prefetch-Control | "off" |
| XDownloadOptions | `string` | X-Download-Options | "noopen" |
| XPermittedCrossDomain | `string` | X-Permitted-Cross-Domain-Policies | "none" |
## Default Config
```go
var ConfigDefault = Config{
XSSProtection: "0",
ContentTypeNosniff: "nosniff",
XFrameOptions: "SAMEORIGIN",
ReferrerPolicy: "no-referrer",
CrossOriginEmbedderPolicy: "require-corp",
CrossOriginOpenerPolicy: "same-origin",
CrossOriginResourcePolicy: "same-origin",
OriginAgentCluster: "?1",
XDNSPrefetchControl: "off",
XDownloadOptions: "noopen",
XPermittedCrossDomain: "none",
}
```

View file

@ -0,0 +1,83 @@
---
id: idempotency
---
# Idempotency
Idempotency middleware for [Fiber](https://github.com/gofiber/fiber) allows for fault-tolerant APIs where duplicate requests — for example due to networking issues on the client-side — do not erroneously cause the same action performed multiple times on the server-side.
Refer to https://datatracker.ietf.org/doc/html/draft-ietf-httpapi-idempotency-key-header-02 for a better understanding.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/idempotency"
)
```
After you initiate your Fiber app, you can use the following possibilities:
### Default Config
```go
app.Use(idempotency.New())
```
### Custom Config
```go
app.Use(idempotency.New(idempotency.Config{
Lifetime: 42 * time.Minute,
// ...
}))
```
### Config
| Property | Type | Description | Default |
|:--------------------|:------------------------|:-----------------------------------------------------------------------------------------|:-------------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | A function for safe methods |
| Lifetime | `time.Duration` | Lifetime is the maximum lifetime of an idempotency key. | 30 * time.Minute |
| KeyHeader | `string` | KeyHeader is the name of the header that contains the idempotency key. | "X-Idempotency-Key" |
| KeyHeaderValidate | `func(string) error` | KeyHeaderValidate defines a function to validate the syntax of the idempotency header. | A function for UUID validation |
| KeepResponseHeaders | `[]string` | KeepResponseHeaders is a list of headers that should be kept from the original response. | nil (keep all headers) |
| Lock | `Locker` | Lock locks an idempotency key. | An in-memory locker |
| Storage | `fiber.Storage` | Storage stores response data by idempotency key. | An in-memory storage |
## Default Config
```go
var ConfigDefault = Config{
Next: func(c *fiber.Ctx) bool {
// Skip middleware if the request was done using a safe HTTP method
return fiber.IsMethodSafe(c.Method())
},
Lifetime: 30 * time.Minute,
KeyHeader: "X-Idempotency-Key",
KeyHeaderValidate: func(k string) error {
if l, wl := len(k), 36; l != wl { // UUID length is 36 chars
return fmt.Errorf("%w: invalid length: %d != %d", ErrInvalidIdempotencyKey, l, wl)
}
return nil
},
KeepResponseHeaders: nil,
Lock: nil, // Set in configDefault so we don't allocate data here.
Storage: nil, // Set in configDefault so we don't allocate data here.
}
```

View file

@ -0,0 +1,243 @@
---
id: keyauth
---
# Keyauth
Key auth middleware provides a key based authentication.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
```go
package main
import (
"crypto/sha256"
"crypto/subtle"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
)
var (
apiKey = "correct horse battery staple"
)
func validateAPIKey(c *fiber.Ctx, key string) (bool, error) {
hashedAPIKey := sha256.Sum256([]byte(apiKey))
hashedKey := sha256.Sum256([]byte(key))
if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
return true, nil
}
return false, keyauth.ErrMissingOrMalformedAPIKey
}
func main() {
app := fiber.New()
// note that the keyauth middleware needs to be defined before the routes are defined!
app.Use(keyauth.New(keyauth.Config{
KeyLookup: "cookie:access_token",
Validator: validateAPIKey,
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated!")
})
app.Listen(":3000")
}
```
**Test:**
```bash
# No api-key specified -> 400 missing
curl http://localhost:3000
#> missing or malformed API Key
curl --cookie "access_token=correct horse battery staple" http://localhost:3000
#> Successfully authenticated!
curl --cookie "access_token=Clearly A Wrong Key" http://localhost:3000
#> missing or malformed API Key
```
For a more detailed example, see also the [`github.com/gofiber/recipes`](https://github.com/gofiber/recipes) repository and specifically the `fiber-envoy-extauthz` repository and the [`keyauth example`](https://github.com/gofiber/recipes/blob/master/fiber-envoy-extauthz/authz/main.go) code.
### Authenticate only certain endpoints
If you want to authenticate only certain endpoints, you can use the `Config` of keyauth and apply a filter function (eg. `authFilter`) like so
```go
package main
import (
"crypto/sha256"
"crypto/subtle"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
"regexp"
"strings"
)
var (
apiKey = "correct horse battery staple"
protectedURLs = []*regexp.Regexp{
regexp.MustCompile("^/authenticated$"),
regexp.MustCompile("^/auth2$"),
}
)
func validateAPIKey(c *fiber.Ctx, key string) (bool, error) {
hashedAPIKey := sha256.Sum256([]byte(apiKey))
hashedKey := sha256.Sum256([]byte(key))
if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
return true, nil
}
return false, keyauth.ErrMissingOrMalformedAPIKey
}
func authFilter(c *fiber.Ctx) bool {
originalURL := strings.ToLower(c.OriginalURL())
for _, pattern := range protectedURLs {
if pattern.MatchString(originalURL) {
return false
}
}
return true
}
func main() {
app := fiber.New()
app.Use(keyauth.New(keyauth.Config{
Next: authFilter,
KeyLookup: "cookie:access_token",
Validator: validateAPIKey,
}))
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Welcome")
})
app.Get("/authenticated", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated!")
})
app.Get("/auth2", func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated 2!")
})
app.Listen(":3000")
}
```
Which results in this
```bash
# / does not need to be authenticated
curl http://localhost:3000
#> Welcome
# /authenticated needs to be authenticated
curl --cookie "access_token=correct horse battery staple" http://localhost:3000/authenticated
#> Successfully authenticated!
# /auth2 needs to be authenticated too
curl --cookie "access_token=correct horse battery staple" http://localhost:3000/auth2
#> Successfully authenticated 2!
```
### Specifying middleware in the handler
```go
package main
import (
"crypto/sha256"
"crypto/subtle"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/keyauth"
)
const (
apiKey = "my-super-secret-key"
)
func main() {
app := fiber.New()
authMiddleware := keyauth.New(keyauth.Config{
Validator: func(c *fiber.Ctx, key string) (bool, error) {
hashedAPIKey := sha256.Sum256([]byte(apiKey))
hashedKey := sha256.Sum256([]byte(key))
if subtle.ConstantTimeCompare(hashedAPIKey[:], hashedKey[:]) == 1 {
return true, nil
}
return false, keyauth.ErrMissingOrMalformedAPIKey
},
})
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Welcome")
})
app.Get("/allowed", authMiddleware, func(c *fiber.Ctx) error {
return c.SendString("Successfully authenticated!")
})
app.Listen(":3000")
}
```
Which results in this
```bash
# / does not need to be authenticated
curl http://localhost:3000
#> Welcome
# /allowed needs to be authenticated too
curl --header "Authorization: Bearer my-super-secret-key" http://localhost:3000/allowed
#> Successfully authenticated!
```
## Config
| Property | Type | Description | Default |
|:---------------|:-----------------------------------------|:-----------------------------------------------------------------------------------------------------|:------------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| SuccessHandler | `fiber.Handler` | SuccessHandler defines a function which is executed for a valid key. | `nil` |
| ErrorHandler | `fiber.ErrorHandler` | ErrorHandler defines a function which is executed for an invalid key. | `401 Invalid or expired key` |
| KeyLookup | `string` | KeyLookup is a string in the form of "`<source>:<name>`" that is used to extract key from the request. | "header:Authorization" |
| AuthScheme | `string` | AuthScheme to be used in the Authorization header. | "Bearer" |
| Validator | `func(*fiber.Ctx, string) (bool, error)` | Validator is a function to validate the key. | A function for key validation |
| ContextKey | `interface{}` | Context key to store the bearer token from the token into context. | "token" |
## Default Config
```go
var ConfigDefault = Config{
SuccessHandler: func(c *fiber.Ctx) error {
return c.Next()
},
ErrorHandler: func(c *fiber.Ctx, err error) error {
if err == ErrMissingOrMalformedAPIKey {
return c.Status(fiber.StatusUnauthorized).SendString(err.Error())
}
return c.Status(fiber.StatusUnauthorized).SendString("Invalid or expired API Key")
},
KeyLookup: "header:" + fiber.HeaderAuthorization,
AuthScheme: "Bearer",
ContextKey: "token",
}
```

View file

@ -0,0 +1,125 @@
---
id: limiter
---
# Limiter
Limiter middleware for [Fiber](https://github.com/gofiber/fiber) that is used to limit repeat requests to public APIs and/or endpoints such as password reset. It is also useful for API clients, web crawling, or other tasks that need to be throttled.
:::note
This middleware uses our [Storage](https://github.com/gofiber/storage) package to support various databases through a single interface. The default configuration for this middleware saves data to memory, see the examples below for other databases.
:::
:::note
This module does not share state with other processes/servers by default.
:::
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/limiter"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(limiter.New())
// Or extend your config for customization
app.Use(limiter.New(limiter.Config{
Next: func(c *fiber.Ctx) bool {
return c.IP() == "127.0.0.1"
},
Max: 20,
Expiration: 30 * time.Second,
KeyGenerator: func(c *fiber.Ctx) string {
return c.Get("x-forwarded-for")
},
LimitReached: func(c *fiber.Ctx) error {
return c.SendFile("./toofast.html")
},
Storage: myCustomStorage{},
}))
```
## Sliding window
Instead of using the standard fixed window algorithm, you can enable the [sliding window](https://en.wikipedia.org/wiki/Sliding_window_protocol) algorithm.
A example of such configuration is:
```go
app.Use(limiter.New(limiter.Config{
Max: 20,
Expiration: 30 * time.Second,
LimiterMiddleware: limiter.SlidingWindow{},
}))
```
This means that every window will take into account the previous window(if there was any). The given formula for the rate is:
```
weightOfPreviousWindpw = previous window's amount request * (whenNewWindow / Expiration)
rate = weightOfPreviousWindpw + current window's amount request.
```
## Config
| Property | Type | Description | Default |
|:-----------------------|:--------------------------|:--------------------------------------------------------------------------------------------|:-----------------------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Max | `int` | Max number of recent connections during `Expiration` seconds before sending a 429 response. | 5 |
| KeyGenerator | `func(*fiber.Ctx) string` | KeyGenerator allows you to generate custom keys, by default c.IP() is used. | A function using c.IP() as the default |
| Expiration | `time.Duration` | Expiration is the time on how long to keep records of requests in memory. | 1 * time.Minute |
| LimitReached | `fiber.Handler` | LimitReached is called when a request hits the limit. | A function sending 429 response |
| SkipFailedRequests | `bool` | When set to true, requests with StatusCode >= 400 won't be counted. | false |
| SkipSuccessfulRequests | `bool` | When set to true, requests with StatusCode < 400 won't be counted. | false |
| Storage | `fiber.Storage` | Store is used to store the state of the middleware. | An in-memory store for this process only |
| LimiterMiddleware | `LimiterHandler` | LimiterMiddleware is the struct that implements a limiter middleware. | A new Fixed Window Rate Limiter |
| Duration (Deprecated) | `time.Duration` | Deprecated: Use Expiration instead | - |
| Store (Deprecated) | `fiber.Storage` | Deprecated: Use Storage instead | - |
| Key (Deprecated) | `func(*fiber.Ctx) string` | Deprecated: Use KeyGenerator instead | - |
:::note
A custom store can be used if it implements the `Storage` interface - more details and an example can be found in `store.go`.
:::
## Default Config
```go
var ConfigDefault = Config{
Max: 5,
Expiration: 1 * time.Minute,
KeyGenerator: func(c *fiber.Ctx) string {
return c.IP()
},
LimitReached: func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusTooManyRequests)
},
SkipFailedRequests: false,
SkipSuccessfulRequests: false,
LimiterMiddleware: FixedWindow{},
}
```
### Custom Storage/Database
You can use any storage from our [storage](https://github.com/gofiber/storage/) package.
```go
storage := sqlite3.New() // From github.com/gofiber/storage/sqlite3
app.Use(limiter.New(limiter.Config{
Storage: storage,
}))
```

View file

@ -0,0 +1,168 @@
---
id: logger
---
# Logger
Logger middleware for [Fiber](https://github.com/gofiber/fiber) that logs HTTP request/response details.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
)
```
:::tip
The order of registration plays a role. Only all routes that are registered after this one will be logged.
The middleware should therefore be one of the first to be registered.
:::
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(logger.New())
// Or extend your config for customization
// Logging remote IP and Port
app.Use(logger.New(logger.Config{
Format: "[${ip}]:${port} ${status} - ${method} ${path}\n",
}))
// Logging Request ID
app.Use(requestid.New())
app.Use(logger.New(logger.Config{
// For more options, see the Config section
Format: "${pid} ${locals:requestid} ${status} - ${method} ${path}\n",
}))
// Changing TimeZone & TimeFormat
app.Use(logger.New(logger.Config{
Format: "${pid} ${status} - ${method} ${path}\n",
TimeFormat: "02-Jan-2006",
TimeZone: "America/New_York",
}))
// Custom File Writer
file, err := os.OpenFile("./123.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
log.Fatalf("error opening file: %v", err)
}
defer file.Close()
app.Use(logger.New(logger.Config{
Output: file,
}))
// Add Custom Tags
app.Use(logger.New(logger.Config{
CustomTags: map[string]logger.LogFunc{
"custom_tag": func(output logger.Buffer, c *fiber.Ctx, data *logger.Data, extraParam string) (int, error) {
return output.WriteString("it is a custom tag")
},
},
}))
// Callback after log is written
app.Use(logger.New(logger.Config{
TimeFormat: time.RFC3339Nano,
TimeZone: "Asia/Shanghai",
Done: func(c *fiber.Ctx, logString []byte) {
if c.Response().StatusCode() != fiber.StatusOK {
reporter.SendToSlack(logString)
}
},
}))
// Disable colors when outputting to default format
app.Use(logger.New(logger.Config{
DisableColors: true,
}))
```
## Config
### Config
| Property | Type | Description | Default |
|:-----------------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------|:------------------------------------------------------------------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Done | `func(*fiber.Ctx, []byte)` | Done is a function that is called after the log string for a request is written to Output, and pass the log string as parameter. | `nil` |
| CustomTags | `map[string]LogFunc` | tagFunctions defines the custom tag action. | `map[string]LogFunc` |
| Format | `string` | Format defines the logging tags. | `${time} \| ${status} \| ${latency} \| ${ip} \| ${method} \| ${path} \| ${error}\n` || TimeFormat | `string` | TimeFormat defines the time format for log timestamps. | `15:04:05` |
| TimeZone | `string` | TimeZone can be specified, such as "UTC" and "America/New_York" and "Asia/Chongqing", etc | `"Local"` |
| TimeInterval | `time.Duration` | TimeInterval is the delay before the timestamp is updated. | `500 * time.Millisecond` |
| Output | `io.Writer` | Output is a writer where logs are written. | `os.Stdout` |
| DisableColors | `bool` | DisableColors defines if the logs output should be colorized. | `false` |
| enableColors | `bool` | Internal field for enabling colors in the log output. (This is not a user-configurable field) | - |
| enableLatency | `bool` | Internal field for enabling latency measurement in logs. (This is not a user-configurable field) | - |
| timeZoneLocation | `*time.Location` | Internal field for the time zone location. (This is not a user-configurable field) | - |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
Done: nil,
Format: "${time} | ${status} | ${latency} | ${ip} | ${method} | ${path} | ${error}\n",
TimeFormat: "15:04:05",
TimeZone: "Local",
TimeInterval: 500 * time.Millisecond,
Output: os.Stdout,
DisableColors: false,
}
```
## Constants
```go
// Logger variables
const (
TagPid = "pid"
TagTime = "time"
TagReferer = "referer"
TagProtocol = "protocol"
TagPort = "port"
TagIP = "ip"
TagIPs = "ips"
TagHost = "host"
TagMethod = "method"
TagPath = "path"
TagURL = "url"
TagUA = "ua"
TagLatency = "latency"
TagStatus = "status" // response status
TagResBody = "resBody" // response body
TagReqHeaders = "reqHeaders"
TagQueryStringParams = "queryParams" // request query parameters
TagBody = "body" // request body
TagBytesSent = "bytesSent"
TagBytesReceived = "bytesReceived"
TagRoute = "route"
TagError = "error"
// DEPRECATED: Use TagReqHeader instead
TagHeader = "header:" // request header
TagReqHeader = "reqHeader:" // request header
TagRespHeader = "respHeader:" // response header
TagQuery = "query:" // request query
TagForm = "form:" // request form
TagCookie = "cookie:" // request cookie
TagLocals = "locals:"
// colors
TagBlack = "black"
TagRed = "red"
TagGreen = "green"
TagYellow = "yellow"
TagBlue = "blue"
TagMagenta = "magenta"
TagCyan = "cyan"
TagWhite = "white"
TagReset = "reset"
)
```

View file

@ -0,0 +1,81 @@
---
id: monitor
---
# Monitor
Monitor middleware for [Fiber](https://github.com/gofiber/fiber) that reports server metrics, inspired by [express-status-monitor](https://github.com/RafalWilinski/express-status-monitor)
:::caution
Monitor is still in beta, API might change in the future!
:::
![](https://i.imgur.com/nHAtBpJ.gif)
### Signatures
```go
func New() fiber.Handler
```
### Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/monitor"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config (Assign the middleware to /metrics)
app.Get("/metrics", monitor.New())
// Or extend your config for customization
// Assign the middleware to /metrics
// and change the Title to `MyService Metrics Page`
app.Get("/metrics", monitor.New(monitor.Config{Title: "MyService Metrics Page"}))
```
You can also access the API endpoint with
`curl -X GET -H "Accept: application/json" http://localhost:3000/metrics` which returns:
```json
{"pid":{ "cpu":0.4568381746582226, "ram":20516864, "conns":3 },
"os": { "cpu":8.759124087593099, "ram":3997155328, "conns":44,
"total_ram":8245489664, "load_avg":0.51 }}
```
## Config
| Property | Type | Description | Default |
|:-----------|:------------------------|:--------------------------------------------------------------------|:----------------------------------------------------------------------------|
| Title | `string` | Metrics page title | "Fiber Monitor" |
| Refresh | `time.Duration` | Refresh period | 3 seconds |
| APIOnly | `bool` | Whether the service should expose only the monitoring API | false |
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| CustomHead | `string` | Custom HTML Code to Head Section(Before End) | empty |
| FontURL | `string` | FontURL for specify font resource path or URL | "https://fonts.googleapis.com/css2?family=Roboto:wght@400;900&display=swap" |
| ChartJsURL | `string` | ChartJsURL for specify ChartJS library path or URL | "https://cdn.jsdelivr.net/npm/chart.js@2.9/dist/Chart.bundle.min.js" |
## Default Config
```go
var ConfigDefault = Config{
Title: defaultTitle,
Refresh: defaultRefresh,
FontURL: defaultFontURL,
ChartJsURL: defaultChartJSURL,
CustomHead: defaultCustomHead,
APIOnly: false,
Next: nil,
index: newIndex(viewBag{
defaultTitle,
defaultRefresh,
defaultFontURL,
defaultChartJSURL,
defaultCustomHead,
}),
}
```

View file

@ -0,0 +1,53 @@
---
id: pprof
---
# Pprof
Pprof middleware for [Fiber](https://github.com/gofiber/fiber) that serves via its HTTP server runtime profiling data in the format expected by the pprof visualization tool. The package is typically only imported for the side effect of registering its HTTP handlers. The handled paths all begin with /debug/pprof/.
## Signatures
```go
func New() fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/pprof"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(pprof.New())
// Or extend your config for customization
// For example, in systems where you have multiple ingress endpoints, it is common to add a URL prefix, like so:
app.Use(pprof.New(pprof.Config{Prefix: "/endpoint-prefix"}))
// This prefix will be added to the default path of "/debug/pprof/", for a resulting URL of: "/endpoint-prefix/debug/pprof/".
```
## Config
| Property | Type | Description | Default |
|:---------|:------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------|:--------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Prefix | `string` | Prefix defines a URL prefix added before "/debug/pprof". Note that it should start with (but not end with) a slash. Example: "/federated-fiber" | "" |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
}
```

View file

@ -0,0 +1,165 @@
---
id: proxy
---
# Proxy
Proxy middleware for [Fiber](https://github.com/gofiber/fiber) that allows you to proxy requests to multiple servers.
## Signatures
```go
// Balancer create a load balancer among multiple upstrem servers.
func Balancer(config Config) fiber.Handler
// Forward performs the given http request and fills the given http response.
func Forward(addr string, clients ...*fasthttp.Client) fiber.Handler
// Do performs the given http request and fills the given http response.
func Do(c *fiber.Ctx, addr string, clients ...*fasthttp.Client) error
// DoRedirects performs the given http request and fills the given http response while following up to maxRedirectsCount redirects.
func DoRedirects(c *fiber.Ctx, addr string, maxRedirectsCount int, clients ...*fasthttp.Client) error
// DoDeadline performs the given request and waits for response until the given deadline.
func DoDeadline(c *fiber.Ctx, addr string, deadline time.Time, clients ...*fasthttp.Client) error
// DoTimeout performs the given request and waits for response during the given timeout duration.
func DoTimeout(c *fiber.Ctx, addr string, timeout time.Duration, clients ...*fasthttp.Client) error
// DomainForward the given http request based on the given domain and fills the given http response
func DomainForward(hostname string, addr string, clients ...*fasthttp.Client) fiber.Handler
// BalancerForward performs the given http request based round robin balancer and fills the given http response
func BalancerForward(servers []string, clients ...*fasthttp.Client) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/proxy"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// if target https site uses a self-signed certificate, you should
// call WithTlsConfig before Do and Forward
proxy.WithTlsConfig(&tls.Config{
InsecureSkipVerify: true,
})
// if you need to use global self-custom client, you should use proxy.WithClient.
proxy.WithClient(&fasthttp.Client{
NoDefaultUserAgentHeader: true,
DisablePathNormalizing: true,
})
// Forward to url
app.Get("/gif", proxy.Forward("https://i.imgur.com/IWaBepg.gif"))
// If you want to forward with a specific domain. You have to use proxy.DomainForward.
app.Get("/payments", proxy.DomainForward("docs.gofiber.io", "http://localhost:8000"))
// Forward to url with local custom client
app.Get("/gif", proxy.Forward("https://i.imgur.com/IWaBepg.gif", &fasthttp.Client{
NoDefaultUserAgentHeader: true,
DisablePathNormalizing: true,
}))
// Make request within handler
app.Get("/:id", func(c *fiber.Ctx) error {
url := "https://i.imgur.com/"+c.Params("id")+".gif"
if err := proxy.Do(c, url); err != nil {
return err
}
// Remove Server header from response
c.Response().Header.Del(fiber.HeaderServer)
return nil
})
// Make proxy requests while following redirects
app.Get("/proxy", func(c *fiber.Ctx) error {
if err := proxy.DoRedirects(c, "http://google.com", 3); err != nil {
return err
}
// Remove Server header from response
c.Response().Header.Del(fiber.HeaderServer)
return nil
})
// Make proxy requests and wait up to 5 seconds before timing out
app.Get("/proxy", func(c *fiber.Ctx) error {
if err := proxy.DoTimeout(c, "http://localhost:3000", time.Second * 5); err != nil {
return err
}
// Remove Server header from response
c.Response().Header.Del(fiber.HeaderServer)
return nil
})
// Make proxy requests, timeout a minute from now
app.Get("/proxy", func(c *fiber.Ctx) error {
if err := proxy.DoDeadline(c, "http://localhost", time.Now().Add(time.Minute)); err != nil {
return err
}
// Remove Server header from response
c.Response().Header.Del(fiber.HeaderServer)
return nil
})
// Minimal round robin balancer
app.Use(proxy.Balancer(proxy.Config{
Servers: []string{
"http://localhost:3001",
"http://localhost:3002",
"http://localhost:3003",
},
}))
// Or extend your balancer for customization
app.Use(proxy.Balancer(proxy.Config{
Servers: []string{
"http://localhost:3001",
"http://localhost:3002",
"http://localhost:3003",
},
ModifyRequest: func(c *fiber.Ctx) error {
c.Request().Header.Add("X-Real-IP", c.IP())
return nil
},
ModifyResponse: func(c *fiber.Ctx) error {
c.Response().Header.Del(fiber.HeaderServer)
return nil
},
}))
// Or this way if the balancer is using https and the destination server is only using http.
app.Use(proxy.BalancerForward([]string{
"http://localhost:3001",
"http://localhost:3002",
"http://localhost:3003",
}))
```
## Config
| Property | Type | Description | Default |
|:----------------|:-----------------------------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|:----------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Servers | `[]string` | Servers defines a list of `<scheme>://<host>` HTTP servers, which are used in a round-robin manner. i.e.: "https://foobar.com, http://www.foobar.com" | (Required) |
| ModifyRequest | `fiber.Handler` | ModifyRequest allows you to alter the request. | `nil` |
| ModifyResponse | `fiber.Handler` | ModifyResponse allows you to alter the response. | `nil` |
| Timeout | `time.Duration` | Timeout is the request timeout used when calling the proxy client. | 1 second |
| ReadBufferSize | `int` | Per-connection buffer size for requests' reading. This also limits the maximum header size. Increase this buffer if your clients send multi-KB RequestURIs and/or multi-KB headers (for example, BIG cookies). | (Not specified) |
| WriteBufferSize | `int` | Per-connection buffer size for responses' writing. | (Not specified) |
| TlsConfig | `*tls.Config` (or `*fasthttp.TLSConfig` in v3) | TLS config for the HTTP client. | `nil` |
| Client | `*fasthttp.LBClient` | Client is a custom client when client config is complex. | `nil` |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
ModifyRequest: nil,
ModifyResponse: nil,
Timeout: fasthttp.DefaultLBClientTimeout,
}
```

View file

@ -0,0 +1,54 @@
---
id: recover
---
# Recover
Recover middleware for [Fiber](https://github.com/gofiber/fiber) that recovers from panics anywhere in the stack chain and handles the control to the centralized [ErrorHandler](https://docs.gofiber.io/guide/error-handling).
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/recover"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(recover.New())
// This panic will be caught by the middleware
app.Get("/", func(c *fiber.Ctx) error {
panic("I'm an error")
})
```
## Config
| Property | Type | Description | Default |
|:------------------|:--------------------------------|:--------------------------------------------------------------------|:-------------------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| EnableStackTrace | `bool` | EnableStackTrace enables handling stack trace. | `false` |
| StackTraceHandler | `func(*fiber.Ctx, interface{})` | StackTraceHandler defines a function to handle stack trace. | defaultStackTraceHandler |
## Default Config
```go
var ConfigDefault = Config{
Next: nil,
EnableStackTrace: false,
StackTraceHandler: defaultStackTraceHandler,
}
```

View file

@ -0,0 +1,68 @@
---
id: redirect
---
# Redirect
Redirection middleware for Fiber.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/redirect"
)
func main() {
app := fiber.New()
app.Use(redirect.New(redirect.Config{
Rules: map[string]string{
"/old": "/new",
"/old/*": "/new/$1",
},
StatusCode: 301,
}))
app.Get("/new", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Get("/new/*", func(c *fiber.Ctx) error {
return c.SendString("Wildcard: " + c.Params("*"))
})
app.Listen(":3000")
}
```
**Test:**
```curl
curl http://localhost:3000/old
curl http://localhost:3000/old/hello
```
## Config
| Property | Type | Description | Default |
|:-----------|:------------------------|:---------------------------------------------------------------------------------------------------------------------------|:-----------------------|
| Next | `func(*fiber.Ctx) bool` | Filter defines a function to skip middleware. | `nil` |
| Rules | `map[string]string` | Rules defines the URL path rewrite rules. The values captured in asterisk can be retrieved by index e.g. $1, $2 and so on. | Required |
| StatusCode | `int` | The status code when redirecting. This is ignored if Redirect is disabled. | 302 Temporary Redirect |
## Default Config
```go
var ConfigDefault = Config{
StatusCode: fiber.StatusFound,
}
```

View file

@ -0,0 +1,62 @@
---
id: requestid
---
# RequestID
RequestID middleware for [Fiber](https://github.com/gofiber/fiber) that adds an identifier to the response.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/requestid"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
app.Use(requestid.New())
// Or extend your config for customization
app.Use(requestid.New(requestid.Config{
Header: "X-Custom-Header",
Generator: func() string {
return "static-id"
},
}))
```
## Config
| Property | Type | Description | Default |
|:-----------|:------------------------|:--------------------------------------------------------------------------------------------------|:---------------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip this middleware when returned true. | `nil` |
| Header | `string` | Header is the header key where to get/set the unique request ID. | "X-Request-ID" |
| Generator | `func() string` | Generator defines a function to generate the unique identifier. | utils.UUID |
| ContextKey | `interface{}` | ContextKey defines the key used when storing the request ID in the locals for a specific request. | "requestid" |
## Default Config
The default config uses a fast UUID generator which will expose the number of
requests made to the server. To conceal this value for better privacy, use the
`utils.UUIDv4` generator.
```go
var ConfigDefault = Config{
Next: nil,
Header: fiber.HeaderXRequestID,
Generator: utils.UUID,
ContextKey: "requestid",
}
```

View file

@ -0,0 +1,58 @@
---
id: rewrite
---
# Rewrite
Rewrite middleware rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links.
## Signatures
```go
func New(config ...Config) fiber.Handler
```
## Config
| Property | Type | Description | Default |
|:---------|:------------------------|:-----------------------------------------------------------------------------------------------------|:-----------|
| Next | `func(*fiber.Ctx) bool` | Next defines a function to skip middleware. | `nil` |
| Rules | `map[string]string` | Rules defines the URL path rewrite rules. The values captured in asterisk can be retrieved by index. | (Required) |
### Examples
```go
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/rewrite"
)
func main() {
app := fiber.New()
app.Use(rewrite.New(rewrite.Config{
Rules: map[string]string{
"/old": "/new",
"/old/*": "/new/$1",
},
}))
app.Get("/new", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Get("/new/*", func(c *fiber.Ctx) error {
return c.SendString("Wildcard: " + c.Params("*"))
})
app.Listen(":3000")
}
```
**Test:**
```curl
curl http://localhost:3000/old
curl http://localhost:3000/old/hello
```

View file

@ -0,0 +1,139 @@
---
id: session
---
# Session
Session middleware for [Fiber](https://github.com/gofiber/fiber).
:::note
This middleware uses our [Storage](https://github.com/gofiber/storage) package to support various databases through a single interface. The default configuration for this middleware saves data to memory, see the examples below for other databases.
:::
## Signatures
```go
func New(config ...Config) *Store
func (s *Store) RegisterType(i interface{})
func (s *Store) Get(c *fiber.Ctx) (*Session, error)
func (s *Store) Delete(id string) error
func (s *Store) Reset() error
func (s *Session) Get(key string) interface{}
func (s *Session) Set(key string, val interface{})
func (s *Session) Delete(key string)
func (s *Session) Destroy() error
func (s *Session) Reset() error
func (s *Session) Regenerate() error
func (s *Session) Save() error
func (s *Session) Fresh() bool
func (s *Session) ID() string
func (s *Session) Keys() []string
```
:::caution
Storing `interface{}` values are limited to built-ins Go types.
:::
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/session"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
// Initialize default config
// This stores all of your app's sessions
store := session.New()
app.Get("/", func(c *fiber.Ctx) error {
// Get session from storage
sess, err := store.Get(c)
if err != nil {
panic(err)
}
// Get value
name := sess.Get("name")
// Set key/value
sess.Set("name", "john")
// Get all Keys
keys := sess.Keys()
// Delete key
sess.Delete("name")
// Destroy session
if err := sess.Destroy(); err != nil {
panic(err)
}
// Sets a specific expiration for this session
sess.SetExpiry(time.Second * 2)
// Save session
if err := sess.Save(); err != nil {
panic(err)
}
return c.SendString(fmt.Sprintf("Welcome %v", name))
})
```
## Config
| Property | Type | Description | Default |
|:------------------------|:----------------|:------------------------------------------------------------------------------------------------------------|:----------------------|
| Expiration | `time.Duration` | Allowed session duration. | `24 * time.Hour` |
| Storage | `fiber.Storage` | Storage interface to store the session data. | `memory.New()` |
| KeyLookup | `string` | KeyLookup is a string in the form of "`<source>:<name>`" that is used to extract session id from the request. | `"cookie:session_id"` |
| CookieDomain | `string` | Domain of the cookie. | `""` |
| CookiePath | `string` | Path of the cookie. | `""` |
| CookieSecure | `bool` | Indicates if cookie is secure. | `false` |
| CookieHTTPOnly | `bool` | Indicates if cookie is HTTP only. | `false` |
| CookieSameSite | `string` | Value of SameSite cookie. | `"Lax"` |
| CookieSessionOnly | `bool` | Decides whether cookie should last for only the browser session. Ignores Expiration if set to true. | `false` |
| KeyGenerator | `func() string` | KeyGenerator generates the session key. | `utils.UUIDv4` |
| CookieName (Deprecated) | `string` | Deprecated: Please use KeyLookup. The session name. | `""` |
## Default Config
```go
var ConfigDefault = Config{
Expiration: 24 * time.Hour,
KeyLookup: "cookie:session_id",
KeyGenerator: utils.UUIDv4,
source: "cookie",
sessionName: "session_id",
}
```
## Constants
```go
const (
SourceCookie Source = "cookie"
SourceHeader Source = "header"
SourceURLQuery Source = "query"
)
```
### Custom Storage/Database
You can use any storage from our [storage](https://github.com/gofiber/storage/) package.
```go
storage := sqlite3.New() // From github.com/gofiber/storage/sqlite3
store := session.New(session.Config{
Storage: storage,
})
```
To use the store, see the [Examples](#examples).

View file

@ -0,0 +1,47 @@
---
id: skip
---
# Skip
Skip middleware for [Fiber](https://github.com/gofiber/fiber) that skips a wrapped handler if a predicate is true.
## Signatures
```go
func New(handler fiber.Handler, exclude func(c *fiber.Ctx) bool) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/skip"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
func main() {
app := fiber.New()
app.Use(skip.New(BasicHandler, func(ctx *fiber.Ctx) bool {
return ctx.Method() == fiber.MethodGet
}))
app.Get("/", func(ctx *fiber.Ctx) error {
return ctx.SendString("It was a GET request!")
})
log.Fatal(app.Listen(":3000"))
}
func BasicHandler(ctx *fiber.Ctx) error {
return ctx.SendString("It was not a GET request!")
}
```
:::tip
app.Use will handle requests from any route, and any method. In the example above, it will only skip if the method is GET.
:::

View file

@ -0,0 +1,146 @@
---
id: timeout
---
# Timeout
There exist two distinct implementations of timeout middleware [Fiber](https://github.com/gofiber/fiber).
**New**
Wraps a `fiber.Handler` with a timeout. If the handler takes longer than the given duration to return, the timeout error is set and forwarded to the centralized [ErrorHandler](https://docs.gofiber.io/error-handling).
:::caution
This has been deprecated since it raises race conditions.
:::
**NewWithContext**
As a `fiber.Handler` wrapper, it creates a context with `context.WithTimeout` and pass it in `UserContext`.
If the context passed executions (eg. DB ops, Http calls) takes longer than the given duration to return, the timeout error is set and forwarded to the centralized `ErrorHandler`.
It does not cancel long running executions. Underlying executions must handle timeout by using `context.Context` parameter.
## Signatures
```go
func New(handler fiber.Handler, timeout time.Duration, timeoutErrors ...error) fiber.Handler
func NewWithContext(handler fiber.Handler, timeout time.Duration, timeoutErrors ...error) fiber.Handler
```
## Examples
Import the middleware package that is part of the Fiber web framework
```go
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/timeout"
)
```
After you initiate your Fiber app, you can use the following possibilities:
```go
func main() {
app := fiber.New()
h := func(c *fiber.Ctx) error {
sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms")
if err := sleepWithContext(c.UserContext(), sleepTime); err != nil {
return fmt.Errorf("%w: execution error", err)
}
return nil
}
app.Get("/foo/:sleepTime", timeout.New(h, 2*time.Second))
log.Fatal(app.Listen(":3000"))
}
func sleepWithContext(ctx context.Context, d time.Duration) error {
timer := time.NewTimer(d)
select {
case <-ctx.Done():
if !timer.Stop() {
<-timer.C
}
return context.DeadlineExceeded
case <-timer.C:
}
return nil
}
```
Test http 200 with curl:
```bash
curl --location -I --request GET 'http://localhost:3000/foo/1000'
```
Test http 408 with curl:
```bash
curl --location -I --request GET 'http://localhost:3000/foo/3000'
```
Use with custom error:
```go
var ErrFooTimeOut = errors.New("foo context canceled")
func main() {
app := fiber.New()
h := func(c *fiber.Ctx) error {
sleepTime, _ := time.ParseDuration(c.Params("sleepTime") + "ms")
if err := sleepWithContextWithCustomError(c.UserContext(), sleepTime); err != nil {
return fmt.Errorf("%w: execution error", err)
}
return nil
}
app.Get("/foo/:sleepTime", timeout.NewWithContext(h, 2*time.Second, ErrFooTimeOut))
log.Fatal(app.Listen(":3000"))
}
func sleepWithContextWithCustomError(ctx context.Context, d time.Duration) error {
timer := time.NewTimer(d)
select {
case <-ctx.Done():
if !timer.Stop() {
<-timer.C
}
return ErrFooTimeOut
case <-timer.C:
}
return nil
}
```
Sample usage with a DB call:
```go
func main() {
app := fiber.New()
db, _ := gorm.Open(postgres.Open("postgres://localhost/foodb"), &gorm.Config{})
handler := func(ctx *fiber.Ctx) error {
tran := db.WithContext(ctx.UserContext()).Begin()
if tran = tran.Exec("SELECT pg_sleep(50)"); tran.Error != nil {
return tran.Error
}
if tran = tran.Commit(); tran.Error != nil {
return tran.Error
}
return nil
}
app.Get("/foo", timeout.NewWithContext(handler, 10*time.Second))
log.Fatal(app.Listen(":3000"))
}
```

View file

@ -0,0 +1,8 @@
{
"label": "Extra",
"position": 4,
"link": {
"type": "generated-index",
"description": "Extra contents for Fiber."
}
}

112
docs/extra/benchmarks.md Normal file
View file

@ -0,0 +1,112 @@
---
id: benchmarks
title: 📊 Benchmarks
description: >-
These benchmarks aim to compare the performance of Fiber and other web
frameworks.
sidebar_position: 2
---
## TechEmpower
[TechEmpower](https://www.techempower.com/benchmarks/#section=data-r19&hw=ph&test=composite) provides a performance comparison of many web application frameworks executing fundamental tasks such as JSON serialization, database access, and server-side template composition.
Each framework is operating in a realistic production configuration. Results are captured on cloud instances and on physical hardware. The test implementations are largely community-contributed and all source is available at the [GitHub repository](https://github.com/TechEmpower/FrameworkBenchmarks).
* Fiber `v1.10.0`
* 28 HT Cores Intel\(R\) Xeon\(R\) Gold 5120 CPU @ 2.20GHz
* 32GB RAM
* Ubuntu 18.04.3 4.15.0-88-generic
* Dedicated Cisco 10-Gbit Ethernet switch.
### Plaintext
The Plaintext test is an exercise of the request-routing fundamentals only, designed to demonstrate the capacity of high-performance platforms in particular. Requests will be sent using HTTP pipelining. The response payload is still small, meaning good performance is still necessary in order to saturate the gigabit Ethernet of the test environment.
See [Plaintext requirements](https://github.com/TechEmpower/FrameworkBenchmarks/wiki/Project-Information-Framework-Tests-Overview#single-database-query)
**Fiber** - **6,162,556** responses per second with an average latency of **2.0** ms.
**Express** - **367,069** responses per second with an average latency of **354.1** ms.
![](/img/plaintext.png)
![Fiber vs Express](/img/plaintext_express.png)
### Data Updates
**Fiber** handled **11,846** responses per second with an average latency of **42.8** ms.
**Express** handled **2,066** responses per second with an average latency of **390.44** ms.
![](/img/data_updates.png)
![Fiber vs Express](/img/data_updates_express.png)
### Multiple Queries
**Fiber** handled **19,664** responses per second with an average latency of **25.7** ms.
**Express** handled **4,302** responses per second with an average latency of **117.2** ms.
![](/img/multiple_queries.png)
![Fiber vs Express](/img/multiple_queries_express.png)
### Single Query
**Fiber** handled **368,647** responses per second with an average latency of **0.7** ms.
**Express** handled **57,880** responses per second with an average latency of **4.4** ms.
![](/img/single_query.png)
![Fiber vs Express](/img/single_query_express.png)
### JSON Serialization
**Fiber** handled **1,146,667** responses per second with an average latency of **0.4** ms.
**Express** handled **244,847** responses per second with an average latency of **1.1** ms.
![](/img/json.png)
![Fiber vs Express](/img/json_express.png)
## Go web framework benchmark
🔗 [https://github.com/smallnest/go-web-framework-benchmark](https://github.com/smallnest/go-web-framework-benchmark)
* **CPU** Intel\(R\) Xeon\(R\) Gold 6140 CPU @ 2.30GHz
* **MEM** 4GB
* **GO** go1.13.6 linux/amd64
* **OS** Linux
The first test case is to mock **0 ms**, **10 ms**, **100 ms**, **500 ms** processing time in handlers.
![](/img/benchmark.png)
The concurrency clients are **5000**.
![](/img/benchmark_latency.png)
Latency is the time of real processing time by web servers. _The smaller is the better._
![](/img/benchmark_alloc.png)
Allocs is the heap allocations by web servers when test is running. The unit is MB. _The smaller is the better._
If we enable **http pipelining**, test result as below:
![](/img/benchmark-pipeline.png)
Concurrency test in **30 ms** processing time, the test result for **100**, **1000**, **5000** clients is:
![](/img/concurrency.png)
![](/img/concurrency_latency.png)
![](/img/concurrency_alloc.png)
If we enable **http pipelining**, test result as below:
![](/img/concurrency-pipeline.png)
Dependency graph for `v1.9.0`
![](/img/graph.svg)

169
docs/extra/faq.md Normal file
View file

@ -0,0 +1,169 @@
---
id: faq
title: 🤔 FAQ
description: >-
List of frequently asked questions. Feel free to open an issue to add your
question to this page.
sidebar_position: 1
---
## How should I structure my application?
There is no definitive answer to this question. The answer depends on the scale of your application and the team that is involved. To be as flexible as possible, Fiber makes no assumptions in terms of structure.
Routes and other application-specific logic can live in as many files as you wish, in any directory structure you prefer. View the following examples for inspiration:
* [gofiber/boilerplate](https://github.com/gofiber/boilerplate)
* [thomasvvugt/fiber-boilerplate](https://github.com/thomasvvugt/fiber-boilerplate)
* [Youtube - Building a REST API using Gorm and Fiber](https://www.youtube.com/watch?v=Iq2qT0fRhAA)
* [embedmode/fiberseed](https://github.com/embedmode/fiberseed)
## How do I handle custom 404 responses?
If you're using v2.32.0 or later, all you need to do is to implement a custom error handler. See below, or see a more detailed explanation at [Error Handling](../guide/error-handling.md#custom-error-handler).
If you're using v2.31.0 or earlier, the error handler will not capture 404 errors. Instead, you need to add a middleware function at the very bottom of the stack \(below all other functions\) to handle a 404 response:
```go title="Example"
app.Use(func(c *fiber.Ctx) error {
return c.Status(fiber.StatusNotFound).SendString("Sorry can't find that!")
})
```
## How can i use live reload ?
[Air](https://github.com/cosmtrek/air) is a handy tool that automatically restarts your Go applications whenever the source code changes, making your development process faster and more efficient.
To use Air in a Fiber project, follow these steps:
1. Install Air by downloading the appropriate binary for your operating system from the GitHub release page or by building the tool directly from source.
2. Create a configuration file for Air in your project directory. This file can be named, for example, .air.toml or air.conf. Here's a sample configuration file that works with Fiber:
```toml
# .air.toml
root = "."
tmp_dir = "tmp"
[build]
cmd = "go build -o ./tmp/main ."
bin = "./tmp/main"
delay = 1000 # ms
exclude_dir = ["assets", "tmp", "vendor"]
include_ext = ["go", "tpl", "tmpl", "html"]
exclude_regex = ["_test\\.go"]
```
3. Start your Fiber application using Air by running the following command in the terminal:
```sh
air
```
As you make changes to your source code, Air will detect them and automatically restart the application.
A complete example demonstrating the use of Air with Fiber can be found in the [Fiber Recipes repository](https://github.com/gofiber/recipes/tree/master/air). This example shows how to configure and use Air in a Fiber project to create an efficient development environment.
## How do I set up an error handler?
To override the default error handler, you can override the default when providing a [Config](../api/fiber.md#config) when initiating a new [Fiber instance](../api/fiber.md#new).
```go title="Example"
app := fiber.New(fiber.Config{
ErrorHandler: func(c *fiber.Ctx, err error) error {
return c.Status(fiber.StatusInternalServerError).SendString(err.Error())
},
})
```
We have a dedicated page explaining how error handling works in Fiber, see [Error Handling](../guide/error-handling.md).
## Which template engines does Fiber support?
Fiber currently supports 9 template engines in our [gofiber/template](https://docs.gofiber.io/template/) middleware:
* [ace](https://docs.gofiber.io/template/ace/)
* [amber](https://docs.gofiber.io/template/amber/)
* [django](https://docs.gofiber.io/template/django/)
* [handlebars](https://docs.gofiber.io/template/handlebars)
* [html](https://docs.gofiber.io/template/html)
* [jet](https://docs.gofiber.io/template/jet)
* [mustache](https://docs.gofiber.io/template/mustache)
* [pug](https://docs.gofiber.io/template/pug)
* [slim](https://docs.gofiber.io/template/pug)
To learn more about using Templates in Fiber, see [Templates](../guide/templates.md).
## Does Fiber have a community chat?
Yes, we have our own [Discord ](https://gofiber.io/discord)server, where we hang out. We have different rooms for every subject.
If you have questions or just want to have a chat, feel free to join us via this **&gt;** [**invite link**](https://gofiber.io/discord) **&lt;**.
![](/img/support-discord.png)
## Does fiber support sub domain routing ?
Yes we do, here are some examples:
This example works v2
```go
package main
import (
"log"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/logger"
)
type Host struct {
Fiber *fiber.App
}
func main() {
// Hosts
hosts := map[string]*Host{}
//-----
// API
//-----
api := fiber.New()
api.Use(logger.New(logger.Config{
Format: "[${ip}]:${port} ${status} - ${method} ${path}\n",
}))
hosts["api.localhost:3000"] = &Host{api}
api.Get("/", func(c *fiber.Ctx) error {
return c.SendString("API")
})
//------
// Blog
//------
blog := fiber.New()
blog.Use(logger.New(logger.Config{
Format: "[${ip}]:${port} ${status} - ${method} ${path}\n",
}))
hosts["blog.localhost:3000"] = &Host{blog}
blog.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Blog")
})
//---------
// Website
//---------
site := fiber.New()
site.Use(logger.New(logger.Config{
Format: "[${ip}]:${port} ${status} - ${method} ${path}\n",
}))
hosts["localhost:3000"] = &Host{site}
site.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Website")
})
// Server
app := fiber.New()
app.Use(func(c *fiber.Ctx) error {
host := hosts[c.Hostname()]
if host == nil {
return c.SendStatus(fiber.StatusNotFound)
} else {
host.Fiber.Handler()(c.Context())
return nil
}
})
log.Fatal(app.Listen(":3000"))
}
```
If more information is needed, please refer to this issue [#750](https://github.com/gofiber/fiber/issues/750)

View file

@ -0,0 +1,8 @@
{
"label": "Guide",
"position": 3,
"link": {
"type": "generated-index",
"description": "Guides for Fiber."
}
}

View file

@ -0,0 +1,128 @@
---
id: error-handling
title: 🐛 Error Handling
description: >-
Fiber supports centralized error handling by returning an error to the handler
which allows you to log errors to external services or send a customized HTTP
response to the client.
sidebar_position: 4
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
## Catching Errors
Its essential to ensure that Fiber catches all errors that occur while running route handlers and middleware. You must return them to the handler function, where Fiber will catch and process them.
<Tabs>
<TabItem value="example" label="Example">
```go
app.Get("/", func(c *fiber.Ctx) error {
// Pass error to Fiber
return c.SendFile("file-does-not-exist")
})
```
</TabItem>
</Tabs>
Fiber does not handle [panics](https://go.dev/blog/defer-panic-and-recover) by default. To recover from a panic thrown by any handler in the stack, you need to include the `Recover` middleware below:
```go title="Example"
package main
import (
"log"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/recover"
)
func main() {
app := fiber.New()
app.Use(recover.New())
app.Get("/", func(c *fiber.Ctx) error {
panic("This panic is caught by fiber")
})
log.Fatal(app.Listen(":3000"))
}
```
You could use Fiber's custom error struct to pass an additional `status code` using `fiber.NewError()`. It's optional to pass a message; if this is left empty, it will default to the status code message \(`404` equals `Not Found`\).
```go title="Example"
app.Get("/", func(c *fiber.Ctx) error {
// 503 Service Unavailable
return fiber.ErrServiceUnavailable
// 503 On vacation!
return fiber.NewError(fiber.StatusServiceUnavailable, "On vacation!")
})
```
## Default Error Handler
Fiber provides an error handler by default. For a standard error, the response is sent as **500 Internal Server Error**. If the error is of type [fiber.Error](https://godoc.org/github.com/gofiber/fiber#Error), the response is sent with the provided status code and message.
```go title="Example"
// Default error handler
var DefaultErrorHandler = func(c *fiber.Ctx, err error) error {
// Status code defaults to 500
code := fiber.StatusInternalServerError
// Retrieve the custom status code if it's a *fiber.Error
var e *fiber.Error
if errors.As(err, &e) {
code = e.Code
}
// Set Content-Type: text/plain; charset=utf-8
c.Set(fiber.HeaderContentType, fiber.MIMETextPlainCharsetUTF8)
// Return status code with error message
return c.Status(code).SendString(err.Error())
}
```
## Custom Error Handler
A custom error handler can be set using a [Config ](../api/fiber.md#config)when initializing a [Fiber instance](../api/fiber.md#new).
In most cases, the default error handler should be sufficient. However, a custom error handler can come in handy if you want to capture different types of errors and take action accordingly e.g., send a notification email or log an error to the centralized system. You can also send customized responses to the client e.g., error page or just a JSON response.
The following example shows how to display error pages for different types of errors.
```go title="Example"
// Create a new fiber instance with custom config
app := fiber.New(fiber.Config{
// Override default error handler
ErrorHandler: func(ctx *fiber.Ctx, err error) error {
// Status code defaults to 500
code := fiber.StatusInternalServerError
// Retrieve the custom status code if it's a *fiber.Error
var e *fiber.Error
if errors.As(err, &e) {
code = e.Code
}
// Send custom error page
err = ctx.Status(code).SendFile(fmt.Sprintf("./%d.html", code))
if err != nil {
// In case the SendFile fails
return ctx.Status(fiber.StatusInternalServerError).SendString("Internal Server Error")
}
// Return from handler
return nil
},
})
// ...
```
> Special thanks to the [Echo](https://echo.labstack.com/) & [Express](https://expressjs.com/) framework for inspiration regarding error handling.

View file

@ -0,0 +1,36 @@
---
id: faster-fiber
title: ⚡ Make Fiber Faster
sidebar_position: 7
---
## Custom JSON Encoder/Decoder
Since Fiber v2.32.0, we use **encoding/json** as default json library due to stability and producibility. However, the standard library is a bit slow compared to 3rd party libraries. If you're not happy with the performance of **encoding/json**, we recommend you to use these libraries:
- [goccy/go-json](https://github.com/goccy/go-json)
- [bytedance/sonic](https://github.com/bytedance/sonic)
- [segmentio/encoding](https://github.com/segmentio/encoding)
- [mailru/easyjson](https://github.com/mailru/easyjson)
- [minio/simdjson-go](https://github.com/minio/simdjson-go)
- [wI2L/jettison](https://github.com/wI2L/jettison)
```go title="Example"
package main
import "github.com/gofiber/fiber/v2"
import "github.com/goccy/go-json"
func main() {
app := fiber.New(fiber.Config{
JSONEncoder: json.Marshal,
JSONDecoder: json.Unmarshal,
})
# ...
}
```
### References
- [Set custom JSON encoder for client](../api/client.md#jsonencoder)
- [Set custom JSON decoder for client](../api/client.md#jsondecoder)
- [Set custom JSON encoder for application](../api/fiber.md#config)
- [Set custom JSON decoder for application](../api/fiber.md#config)

79
docs/guide/grouping.md Normal file
View file

@ -0,0 +1,79 @@
---
id: grouping
title: 🎭 Grouping
sidebar_position: 2
---
:::info
In general, the Group functionality in Fiber behaves similarly to ExpressJS. Groups are declared virtually and all routes declared within the group are flattened into a single list with a prefix, which is then checked by the framework in the order it was declared. This means that the behavior of Group in Fiber is identical to that of ExpressJS.
:::
## Paths
Like **Routing**, groups can also have paths that belong to a cluster.
```go
func main() {
app := fiber.New()
api := app.Group("/api", middleware) // /api
v1 := api.Group("/v1", middleware) // /api/v1
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user
v2 := api.Group("/v2", middleware) // /api/v2
v2.Get("/list", handler) // /api/v2/list
v2.Get("/user", handler) // /api/v2/user
log.Fatal(app.Listen(":3000"))
}
```
A **Group** of paths can have an optional handler.
```go
func main() {
app := fiber.New()
api := app.Group("/api") // /api
v1 := api.Group("/v1") // /api/v1
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user
v2 := api.Group("/v2") // /api/v2
v2.Get("/list", handler) // /api/v2/list
v2.Get("/user", handler) // /api/v2/user
log.Fatal(app.Listen(":3000"))
}
```
:::caution
Running **/api**, **/v1** or **/v2** will result in **404** error, make sure you have the errors set.
:::
## Group Handlers
Group handlers can also be used as a routing path but they must have **Next** added to them so that the flow can continue.
```go
func main() {
app := fiber.New()
handler := func(c *fiber.Ctx) error {
return c.SendStatus(fiber.StatusOK)
}
api := app.Group("/api") // /api
v1 := api.Group("/v1", func(c *fiber.Ctx) error { // middleware for /api/v1
c.Set("Version", "v1")
return c.Next()
})
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user
log.Fatal(app.Listen(":3000"))
}
```

218
docs/guide/hooks.md Normal file
View file

@ -0,0 +1,218 @@
---
id: hooks
title: 🎣 Hooks
sidebar_position: 6
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
With Fiber v2.30.0, you can execute custom user functions when to run some methods. Here is a list of this hooks:
- [OnRoute](#onroute)
- [OnName](#onname)
- [OnGroup](#ongroup)
- [OnGroupName](#ongroupname)
- [OnListen](#onlisten)
- [OnFork](#onfork)
- [OnShutdown](#onshutdown)
- [OnMount](#onmount)
## Constants
```go
// Handlers define a function to create hooks for Fiber.
type OnRouteHandler = func(Route) error
type OnNameHandler = OnRouteHandler
type OnGroupHandler = func(Group) error
type OnGroupNameHandler = OnGroupHandler
type OnListenHandler = func(ListenData) error
type OnForkHandler = func(int) error
type OnShutdownHandler = func() error
type OnMountHandler = func(*App) error
```
## OnRoute
OnRoute is a hook to execute user functions on each route registeration. Also you can get route properties by **route** parameter.
```go title="Signature"
func (h *Hooks) OnRoute(handler ...OnRouteHandler)
```
## OnName
OnName is a hook to execute user functions on each route naming. Also you can get route properties by **route** parameter.
:::caution
OnName only works with naming routes, not groups.
:::
```go title="Signature"
func (h *Hooks) OnName(handler ...OnNameHandler)
```
<Tabs>
<TabItem value="onname-example" label="OnName Example">
```go
package main
import (
"fmt"
"github.com/gofiber/fiber/v2"
)
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString(c.Route().Name)
}).Name("index")
app.Hooks().OnName(func(r fiber.Route) error {
fmt.Print("Name: " + r.Name + ", ")
return nil
})
app.Hooks().OnName(func(r fiber.Route) error {
fmt.Print("Method: " + r.Method + "\n")
return nil
})
app.Get("/add/user", func(c *fiber.Ctx) error {
return c.SendString(c.Route().Name)
}).Name("addUser")
app.Delete("/destroy/user", func(c *fiber.Ctx) error {
return c.SendString(c.Route().Name)
}).Name("destroyUser")
app.Listen(":5000")
}
// Results:
// Name: addUser, Method: GET
// Name: destroyUser, Method: DELETE
```
</TabItem>
</Tabs>
## OnGroup
OnGroup is a hook to execute user functions on each group registeration. Also you can get group properties by **group** parameter.
```go title="Signature"
func (h *Hooks) OnGroup(handler ...OnGroupHandler)
```
## OnGroupName
OnGroupName is a hook to execute user functions on each group naming. Also you can get group properties by **group** parameter.
:::caution
OnGroupName only works with naming groups, not routes.
:::
```go title="Signature"
func (h *Hooks) OnGroupName(handler ...OnGroupNameHandler)
```
## OnListen
OnListen is a hook to execute user functions on Listen, ListenTLS, Listener.
```go title="Signature"
func (h *Hooks) OnListen(handler ...OnListenHandler)
```
<Tabs>
<TabItem value="onlisten-example" label="OnListen Example">
```go
app := fiber.New(fiber.Config{
DisableStartupMessage: true,
})
app.Hooks().OnListen(func(listenData fiber.ListenData) error {
if fiber.IsChild() {
return nil
}
scheme := "http"
if data.TLS {
scheme = "https"
}
log.Println(scheme + "://" + listenData.Host + ":" + listenData.Port)
return nil
})
app.Listen(":5000")
```
</TabItem>
</Tabs>
## OnFork
OnFork is a hook to execute user functions on Fork.
```go title="Signature"
func (h *Hooks) OnFork(handler ...OnForkHandler)
```
## OnShutdown
OnShutdown is a hook to execute user functions after Shutdown.
```go title="Signature"
func (h *Hooks) OnShutdown(handler ...OnShutdownHandler)
```
## OnMount
OnMount is a hook to execute user function after mounting process. The mount event is fired when sub-app is mounted on a parent app. The parent app is passed as a parameter. It works for app and group mounting.
```go title="Signature"
func (h *Hooks) OnMount(handler ...OnMountHandler)
```
<Tabs>
<TabItem value="onmount-example" label="OnMount Example">
```go
package main
import (
"fmt"
"github.com/gofiber/fiber/v2"
)
func main() {
app := New()
app.Get("/", testSimpleHandler).Name("x")
subApp := New()
subApp.Get("/test", testSimpleHandler)
subApp.Hooks().OnMount(func(parent *fiber.App) error {
fmt.Print("Mount path of parent app: "+parent.MountPath())
// ...
return nil
})
app.Mount("/sub", subApp)
}
// Result:
// Mount path of parent app:
```
</TabItem>
</Tabs>
:::caution
OnName/OnRoute/OnGroup/OnGroupName hooks are mount-sensitive. If you use one of these routes on sub app and you mount it; paths of routes and groups will start with mount prefix.

294
docs/guide/routing.md Normal file
View file

@ -0,0 +1,294 @@
---
id: routing
title: 🔌 Routing
description: >-
Routing refers to how an application's endpoints (URIs) respond to client
requests.
sidebar_position: 1
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import RoutingHandler from './../partials/routing/handler.md';
## Handlers
<RoutingHandler />
## Paths
Route paths, combined with a request method, define the endpoints at which requests can be made. Route paths can be **strings** or **string patterns**.
**Examples of route paths based on strings**
```go
// This route path will match requests to the root route, "/":
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("root")
})
// This route path will match requests to "/about":
app.Get("/about", func(c *fiber.Ctx) error {
return c.SendString("about")
})
// This route path will match requests to "/random.txt":
app.Get("/random.txt", func(c *fiber.Ctx) error {
return c.SendString("random.txt")
})
```
As with the expressJs framework, the order of the route declaration plays a role.
When a request is received, the routes are checked in the order in which they are declared.
:::info
So please be careful to write routes with variable parameters after the routes that contain fixed parts, so that these variable parts do not match instead and unexpected behavior occurs.
:::
## Parameters
Route parameters are dynamic elements in the route, which are **named** or **not named segments**. This segments that are used to capture the values specified at their position in the URL. The obtained values can be retrieved using the [Params](https://fiber.wiki/context#params) function, with the name of the route parameter specified in the path as their respective keys or for unnamed parameters the character\(\*, +\) and the counter of this.
The characters :, +, and \* are characters that introduce a parameter.
Greedy parameters are indicated by wildcard\(\*\) or plus\(+\) signs.
The routing also offers the possibility to use optional parameters, for the named parameters these are marked with a final "?", unlike the plus sign which is not optional, you can use the wildcard character for a parameter range which is optional and greedy.
**Example of define routes with route parameters**
```go
// Parameters
app.Get("/user/:name/books/:title", func(c *fiber.Ctx) error {
fmt.Fprintf(c, "%s\n", c.Params("name"))
fmt.Fprintf(c, "%s\n", c.Params("title"))
return nil
})
// Plus - greedy - not optional
app.Get("/user/+", func(c *fiber.Ctx) error {
return c.SendString(c.Params("+"))
})
// Optional parameter
app.Get("/user/:name?", func(c *fiber.Ctx) error {
return c.SendString(c.Params("name"))
})
// Wildcard - greedy - optional
app.Get("/user/*", func(c *fiber.Ctx) error {
return c.SendString(c.Params("*"))
})
// This route path will match requests to "/v1/some/resource/name:customVerb", since the parameter character is escaped
app.Get(`/v1/some/resource/name\:customVerb`, func(c *fiber.Ctx) error {
return c.SendString("Hello, Community")
})
```
:::info
Since the hyphen \(`-`\) and the dot \(`.`\) are interpreted literally, they can be used along with route parameters for useful purposes.
:::
:::info
All special parameter characters can also be escaped with `"\\"` and lose their value, so you can use them in the route if you want, like in the custom methods of the [google api design guide](https://cloud.google.com/apis/design/custom_methods). It's recommended to use backticks `` ` `` because in go's regex documentation, they always use backticks to make sure it is unambiguous and the escape character doesn't interfere with regex patterns in an unexpected way.
:::
```go
// http://localhost:3000/plantae/prunus.persica
app.Get("/plantae/:genus.:species", func(c *fiber.Ctx) error {
fmt.Fprintf(c, "%s.%s\n", c.Params("genus"), c.Params("species"))
return nil // prunus.persica
})
```
```go
// http://localhost:3000/flights/LAX-SFO
app.Get("/flights/:from-:to", func(c *fiber.Ctx) error {
fmt.Fprintf(c, "%s-%s\n", c.Params("from"), c.Params("to"))
return nil // LAX-SFO
})
```
Our intelligent router recognizes that the introductory parameter characters should be part of the request route in this case and can process them as such.
```go
// http://localhost:3000/shop/product/color:blue/size:xs
app.Get("/shop/product/color::color/size::size", func(c *fiber.Ctx) error {
fmt.Fprintf(c, "%s:%s\n", c.Params("color"), c.Params("size"))
return nil // blue:xs
})
```
In addition, several parameters in a row and several unnamed parameter characters in the route, such as the wildcard or plus character, are possible, which greatly expands the possibilities of the router for the user.
```go
// GET /@v1
// Params: "sign" -> "@", "param" -> "v1"
app.Get("/:sign:param", handler)
// GET /api-v1
// Params: "name" -> "v1"
app.Get("/api-:name", handler)
// GET /customer/v1/cart/proxy
// Params: "*1" -> "customer/", "*2" -> "/cart"
app.Get("/*v1*/proxy", handler)
// GET /v1/brand/4/shop/blue/xs
// Params: "*1" -> "brand/4", "*2" -> "blue/xs"
app.Get("/v1/*/shop/*", handler)
```
We have adapted the routing strongly to the express routing, but currently without the possibility of the regular expressions, because they are quite slow. The possibilities can be tested with version 0.1.7 \(express 4\) in the online [Express route tester](http://forbeslindesay.github.io/express-route-tester/).
### Constraints
Route constraints execute when a match has occurred to the incoming URL and the URL path is tokenized into route values by parameters. The feature was intorduced in `v2.37.0` and inspired by [.NET Core](https://docs.microsoft.com/en-us/aspnet/core/fundamentals/routing?view=aspnetcore-6.0#route-constraints).
:::caution
Constraints aren't validation for parameters. If constraints aren't valid for a parameter value, Fiber returns **404 handler**.
:::
| Constraint | Example | Example matches |
| ----------------- | ------------------------------------ | ------------------------------------------------------------------------------------------- |
| int | `:id<int\>` | 123456789, -123456789 |
| bool | `:active<bool\>` | true,false |
| guid | `:id<guid\>` | CD2C1638-1638-72D5-1638-DEADBEEF1638 |
| float | `:weight<float\>` | 1.234, -1,001.01e8 |
| minLen(value) | `:username<minLen(4)\>` | Test (must be at least 4 characters) |
| maxLen(value) | `:filename<maxLen(8)\>` | MyFile (must be no more than 8 characters |
| len(length) | `:filename<len(12)\>` | somefile.txt (exactly 12 characters) |
| min(value) | `:age<min(18)\>` | 19 (Integer value must be at least 18) |
| max(value) | `:age<max(120)\>` | 91 (Integer value must be no more than 120) |
| range(min,max) | `:age<range(18,120)\>` | 91 (Integer value must be at least 18 but no more than 120) |
| alpha | `:name<alpha\>` | Rick (String must consist of one or more alphabetical characters, a-z and case-insensitive) |
| datetime | `:dob<datetime(2006\\\\-01\\\\-02)\>` | 2005-11-01 |
| regex(expression) | `:date<regex(\\d{4}-\\d{2}-\\d{2})\>` | 2022-08-27 (Must match regular expression) |
**Examples**
<Tabs>
<TabItem value="single-constraint" label="Single Constraint">
```go
app.Get("/:test<min(5)>", func(c *fiber.Ctx) error {
return c.SendString(c.Params("test"))
})
// curl -X GET http://localhost:3000/12
// 12
// curl -X GET http://localhost:3000/1
// Cannot GET /1
```
</TabItem>
<TabItem value="multiple-constraints" label="Multiple Constraints">
You can use `;` for multiple constraints.
```go
app.Get("/:test<min(100);maxLen(5)>", func(c *fiber.Ctx) error {
return c.SendString(c.Params("test"))
})
// curl -X GET http://localhost:3000/120000
// Cannot GET /120000
// curl -X GET http://localhost:3000/1
// Cannot GET /1
// curl -X GET http://localhost:3000/250
// 250
```
</TabItem>
<TabItem value="regex-constraint" label="Regex Constraint">
Fiber precompiles regex query when to register routes. So there're no performance overhead for regex constraint.
```go
app.Get(`/:date<regex(\d{4}-\d{2}-\d{2})>`, func(c *fiber.Ctx) error {
return c.SendString(c.Params("date"))
})
// curl -X GET http://localhost:3000/125
// Cannot GET /125
// curl -X GET http://localhost:3000/test
// Cannot GET /test
// curl -X GET http://localhost:3000/2022-08-27
// 2022-08-27
```
</TabItem>
</Tabs>
:::caution
You should use `\\` before routing-specific characters when to use datetime constraint (`*`, `+`, `?`, `:`, `/`, `<`, `>`, `;`, `(`, `)`), to avoid wrong parsing.
:::
**Optional Parameter Example**
You can impose constraints on optional parameters as well.
```go
app.Get("/:test<int>?", func(c *fiber.Ctx) error {
return c.SendString(c.Params("test"))
})
// curl -X GET http://localhost:3000/42
// 42
// curl -X GET http://localhost:3000/
//
// curl -X GET http://localhost:3000/7.0
// Cannot GET /7.0
```
## Middleware
Functions that are designed to make changes to the request or response are called **middleware functions**. The [Next](../api/ctx.md#next) is a **Fiber** router function, when called, executes the **next** function that **matches** the current route.
**Example of a middleware function**
```go
app.Use(func(c *fiber.Ctx) error {
// Set a custom header on all responses:
c.Set("X-Custom-Header", "Hello, World")
// Go to next middleware:
return c.Next()
})
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
```
`Use` method path is a **mount**, or **prefix** path, and limits middleware to only apply to any paths requested that begin with it.
### Constraints on Adding Routes Dynamically
:::caution
Adding routes dynamically after the application has started is not supported due to design and performance considerations. Make sure to define all your routes before the application starts.
:::
## Grouping
If you have many endpoints, you can organize your routes using `Group`.
```go
func main() {
app := fiber.New()
api := app.Group("/api", middleware) // /api
v1 := api.Group("/v1", middleware) // /api/v1
v1.Get("/list", handler) // /api/v1/list
v1.Get("/user", handler) // /api/v1/user
v2 := api.Group("/v2", middleware) // /api/v2
v2.Get("/list", handler) // /api/v2/list
v2.Get("/user", handler) // /api/v2/user
log.Fatal(app.Listen(":3000"))
}
```
More information about this in our [Grouping Guide](./grouping.md)

267
docs/guide/templates.md Normal file
View file

@ -0,0 +1,267 @@
---
id: templates
title: 📝 Templates
description: Fiber supports server-side template engines.
sidebar_position: 3
---
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
Templates are a great tool to render dynamic content without using a separate frontend framework.
## Template Engines
Fiber allows you to provide a custom template engine at app initialization.
```go
app := fiber.New(fiber.Config{
// Pass in Views Template Engine
Views: engine,
// Default global path to search for views (can be overriden when calling Render())
ViewsLayout: "layouts/main",
// Enables/Disables access to `ctx.Locals()` entries in rendered views
// (defaults to false)
PassLocalsToViews: false,
})
```
### Supported Engines
The Fiber team maintains a [templates](https://docs.gofiber.io/template) package that provides wrappers for multiple template engines:
* [ace](https://docs.gofiber.io/template/ace/)
* [amber](https://docs.gofiber.io/template/amber/)
* [django](https://docs.gofiber.io/template/django/)
* [handlebars](https://docs.gofiber.io/template/handlebars)
* [html](https://docs.gofiber.io/template/html)
* [jet](https://docs.gofiber.io/template/jet)
* [mustache](https://docs.gofiber.io/template/mustache)
* [pug](https://docs.gofiber.io/template/pug)
* [slim](https://docs.gofiber.io/template/slim)
:::info
Custom template engines can implement the `Views` interface to be supported in Fiber.
:::
```go title="Views interface"
type Views interface {
// Fiber executes Load() on app initialization to load/parse the templates
Load() error
// Outputs a template to the provided buffer using the provided template,
// template name, and binded data
Render(io.Writer, string, interface{}, ...string) error
}
```
:::note
The `Render` method is linked to the [**ctx.Render\(\)**](../api/ctx.md#render) function that accepts a template name and binding data.
:::
## Rendering Templates
Once an engine is set up, a route handler can call the [**ctx.Render\(\)**](../api/ctx.md#render) function with a template name and binded data to send the rendered template.
```go title="Signature"
func (c *Ctx) Render(name string, bind Map, layouts ...string) error
```
:::info
By default, [**ctx.Render\(\)**](../api/ctx.md#render) searches for the template name in the `ViewsLayout` path. To override this setting, provide the path(s) in the `layouts` argument.
:::
<Tabs>
<TabItem value="example" label="Example">
```go
app.Get("/", func(c *fiber.Ctx) error {
return c.Render("index", fiber.Map{
"Title": "Hello, World!",
})
})
```
</TabItem>
<TabItem value="index" label="layouts/index.html">
```html
<!DOCTYPE html>
<html>
<body>
<h1>{{.Title}}</h1>
</body>
</html>
```
</TabItem>
</Tabs>
:::caution
If the Fiber config option `PassLocalsToViews` is enabled, then all locals set using `ctx.Locals(key, value)` will be passed to the template. It is important to avoid clashing keys when using this setting.
:::
## Advanced Templating
### Custom Functions
Fiber supports adding custom functions to templates.
#### AddFunc
Adds a global function to all templates.
```go title="Signature"
func (e *Engine) AddFunc(name string, fn interface{}) IEngineCore
```
<Tabs>
<TabItem value="add-func-example" label="AddFunc Example">
```go
// Add `ToUpper` to engine
engine := html.New("./views", ".html")
engine.AddFunc("ToUpper", func(s string) string {
return strings.ToUpper(s)
}
// Initialize Fiber App
app := fiber.New(fiber.Config{
Views: engine,
})
app.Get("/", func (c *fiber.Ctx) error {
return c.Render("index", fiber.Map{
"Content": "hello, world!"
})
})
```
</TabItem>
<TabItem value="add-func-template" label="views/index.html">
```html
<!DOCTYPE html>
<html>
<body>
<p>This will be in {{ToUpper "all caps"}}:</p>
<p>{{ToUpper .Content}}</p>
</body>
</html>
```
</TabItem>
</Tabs>
#### AddFuncMap
Adds a Map of functions (keyed by name) to all templates.
```go title="Signature"
func (e *Engine) AddFuncMap(m map[string]interface{}) IEngineCore
```
<Tabs>
<TabItem value="add-func-map-example" label="AddFuncMap Example">
```go
// Add `ToUpper` to engine
engine := html.New("./views", ".html")
engine.AddFuncMap(map[string]interface{}{
"ToUpper": func(s string) string {
return strings.ToUpper(s)
},
})
// Initialize Fiber App
app := fiber.New(fiber.Config{
Views: engine,
})
app.Get("/", func (c *fiber.Ctx) error {
return c.Render("index", fiber.Map{
"Content": "hello, world!"
})
})
```
</TabItem>
<TabItem value="add-func-map-template" label="views/index.html">
```html
<!DOCTYPE html>
<html>
<body>
<p>This will be in {{ToUpper "all caps"}}:</p>
<p>{{ToUpper .Content}}</p>
</body>
</html>
```
</TabItem>
</Tabs>
* For more advanced template documentation, please visit the [gofiber/template GitHub Repository](https://github.com/gofiber/template).
## Full Example
<Tabs>
<TabItem value="example" label="Example">
```go
package main
import (
"log"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/template/html/v2"
)
func main() {
// Initialize standard Go html template engine
engine := html.New("./views", ".html")
// If you want to use another engine,
// just replace with following:
// Create a new engine with django
// engine := django.New("./views", ".django")
app := fiber.New(fiber.Config{
Views: engine,
})
app.Get("/", func(c *fiber.Ctx) error {
// Render index template
return c.Render("index", fiber.Map{
"Title": "Go Fiber Template Example",
"Description": "An example template",
"Greeting": "Hello, world!",
});
})
log.Fatal(app.Listen(":3000"))
}
```
</TabItem>
<TabItem value="index" label="views/index.html">
```html
<!DOCTYPE html>
<html>
<head>
<title>{{.Title}}</title>
<meta name="description" content="{{.Description}}">
</head>
<body>
<h1>{{.Title}}</h1>
<p>{{.Greeting}}</p>
</body>
</html>
```
</TabItem>
</Tabs>

168
docs/guide/validation.md Normal file
View file

@ -0,0 +1,168 @@
---
id: validation
title: 🔎 Validation
sidebar_position: 5
---
## Validator package
Fiber can make _great_ use of the validator package to ensure correct validation of data to store.
- [Official validator Github page \(Installation, use, examples..\).](https://github.com/go-playground/validator)
You can find the detailed descriptions of the _validations_ used in the fields contained on the structs below:
- [Detailed docs](https://pkg.go.dev/github.com/go-playground/validator?tab=doc)
```go title="Validation Example"
package main
import (
"fmt"
"log"
"strings"
"github.com/go-playground/validator/v10"
"github.com/gofiber/fiber/v2"
)
type (
User struct {
Name string `validate:"required,min=5,max=20"` // Required field, min 5 char long max 20
Age int `validate:"required,teener"` // Required field, and client needs to implement our 'teener' tag format which we'll see later
}
ErrorResponse struct {
Error bool
FailedField string
Tag string
Value interface{}
}
XValidator struct {
validator *validator.Validate
}
GlobalErrorHandlerResp struct {
Success bool `json:"success"`
Message string `json:"message"`
}
)
// This is the validator instance
// for more information see: https://github.com/go-playground/validator
var validate = validator.New()
func (v XValidator) Validate(data interface{}) []ErrorResponse {
validationErrors := []ErrorResponse{}
errs := validate.Struct(data)
if errs != nil {
for _, err := range errs.(validator.ValidationErrors) {
// In this case data object is actually holding the User struct
var elem ErrorResponse
elem.FailedField = err.Field() // Export struct field name
elem.Tag = err.Tag() // Export struct tag
elem.Value = err.Value() // Export field value
elem.Error = true
validationErrors = append(validationErrors, elem)
}
}
return validationErrors
}
func main() {
myValidator := &XValidator{
validator: validate,
}
app := fiber.New(fiber.Config{
// Global custom error handler
ErrorHandler: func(c *fiber.Ctx, err error) error {
return c.Status(fiber.StatusBadRequest).JSON(GlobalErrorHandlerResp{
Success: false,
Message: err.Error(),
})
},
})
// Custom struct validation tag format
myValidator.validator.RegisterValidation("teener", func(fl validator.FieldLevel) bool {
// User.Age needs to fit our needs, 12-18 years old.
return fl.Field().Int() >= 12 && fl.Field().Int() <= 18
})
app.Get("/", func(c *fiber.Ctx) error {
user := &User{
Name: c.Query("name"),
Age: c.QueryInt("age"),
}
// Validation
if errs := myValidator.Validate(user); len(errs) > 0 && errs[0].Error {
errMsgs := make([]string, 0)
for _, err := range errs {
errMsgs = append(errMsgs, fmt.Sprintf(
"[%s]: '%v' | Needs to implement '%s'",
err.FailedField,
err.Value,
err.Tag,
))
}
return &fiber.Error{
Code: fiber.ErrBadRequest.Code,
Message: strings.Join(errMsgs, " and "),
}
}
// Logic, validated with success
return c.SendString("Hello, World!")
})
log.Fatal(app.Listen(":3000"))
}
/**
OUTPUT
[1]
Request:
GET http://127.0.0.1:3000/
Response:
{"success":false,"message":"[Name]: '' | Needs to implement 'required' and [Age]: '0' | Needs to implement 'required'"}
[2]
Request:
GET http://127.0.0.1:3000/?name=efdal&age=9
Response:
{"success":false,"message":"[Age]: '9' | Needs to implement 'teener'"}
[3]
Request:
GET http://127.0.0.1:3000/?name=efdal&age=
Response:
{"success":false,"message":"[Age]: '0' | Needs to implement 'required'"}
[4]
Request:
GET http://127.0.0.1:3000/?name=efdal&age=18
Response:
Hello, World!
**/
```

195
docs/intro.md Normal file
View file

@ -0,0 +1,195 @@
---
slug: /
id: welcome
title: 👋 Welcome
sidebar_position: 1
---
An online API documentation with examples so you can start building web apps with Fiber right away!
**Fiber** is an [Express](https://github.com/expressjs/express) inspired **web framework** built on top of [Fasthttp](https://github.com/valyala/fasthttp), the **fastest** HTTP engine for [Go](https://go.dev/doc/). Designed to **ease** things up for **fast** development with **zero memory allocation** and **performance** in mind.
These docs are for **Fiber v2**, which was released on **September 15th, 2020**.
### Installation
First of all, [download](https://go.dev/dl/) and install Go. `1.17` or higher is required.
Installation is done using the [`go get`](https://pkg.go.dev/cmd/go/#hdr-Add_dependencies_to_current_module_and_install_them) command:
```bash
go get github.com/gofiber/fiber/v2
```
### Zero Allocation
Some values returned from \***fiber.Ctx** are **not** immutable by default.
Because fiber is optimized for **high-performance**, values returned from **fiber.Ctx** are **not** immutable by default and **will** be re-used across requests. As a rule of thumb, you **must** only use context values within the handler, and you **must not** keep any references. As soon as you return from the handler, any values you have obtained from the context will be re-used in future requests and will change below your feet. Here is an example:
```go
func handler(c *fiber.Ctx) error {
// Variable is only valid within this handler
result := c.Params("foo")
// ...
}
```
If you need to persist such values outside the handler, make copies of their **underlying buffer** using the [copy](https://pkg.go.dev/builtin/#copy) builtin. Here is an example for persisting a string:
```go
func handler(c *fiber.Ctx) error {
// Variable is only valid within this handler
result := c.Params("foo")
// Make a copy
buffer := make([]byte, len(result))
copy(buffer, result)
resultCopy := string(buffer)
// Variable is now valid forever
// ...
}
```
We created a custom `CopyString` function that does the above and is available under [gofiber/utils](https://github.com/gofiber/fiber/tree/master/utils).
```go
app.Get("/:foo", func(c *fiber.Ctx) error {
// Variable is now immutable
result := utils.CopyString(c.Params("foo"))
// ...
})
```
Alternatively, you can also use the `Immutable` setting. It will make all values returned from the context immutable, allowing you to persist them anywhere. Of course, this comes at the cost of performance.
```go
app := fiber.New(fiber.Config{
Immutable: true,
})
```
For more information, please check [**\#426**](https://github.com/gofiber/fiber/issues/426) and [**\#185**](https://github.com/gofiber/fiber/issues/185).
### Hello, World!
Embedded below is essentially the most straightforward **Fiber** app you can create:
```go
package main
import "github.com/gofiber/fiber/v2"
func main() {
app := fiber.New()
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
app.Listen(":3000")
}
```
```text
go run server.go
```
Browse to `http://localhost:3000` and you should see `Hello, World!` on the page.
### Basic routing
Routing refers to determining how an application responds to a client request to a particular endpoint, which is a URI (or path) and a specific HTTP request method (`GET`, `PUT`, `POST`, etc.).
Each route can have **multiple handler functions** that are executed when the route is matched.
Route definition takes the following structures:
```go
// Function signature
app.Method(path string, ...func(*fiber.Ctx) error)
```
- `app` is an instance of **Fiber**
- `Method` is an [HTTP request method](https://docs.gofiber.io/api/app#route-handlers): `GET`, `PUT`, `POST`, etc.
- `path` is a virtual path on the server
- `func(*fiber.Ctx) error` is a callback function containing the [Context](https://docs.gofiber.io/api/ctx) executed when the route is matched
**Simple route**
```go
// Respond with "Hello, World!" on root path, "/"
app.Get("/", func(c *fiber.Ctx) error {
return c.SendString("Hello, World!")
})
```
**Parameters**
```go
// GET http://localhost:8080/hello%20world
app.Get("/:value", func(c *fiber.Ctx) error {
return c.SendString("value: " + c.Params("value"))
// => Get request with value: hello world
})
```
**Optional parameter**
```go
// GET http://localhost:3000/john
app.Get("/:name?", func(c *fiber.Ctx) error {
if c.Params("name") != "" {
return c.SendString("Hello " + c.Params("name"))
// => Hello john
}
return c.SendString("Where is john?")
})
```
**Wildcards**
```go
// GET http://localhost:3000/api/user/john
app.Get("/api/*", func(c *fiber.Ctx) error {
return c.SendString("API path: " + c.Params("*"))
// => API path: user/john
})
```
### Static files
To serve static files such as **images**, **CSS**, and **JavaScript** files, replace your function handler with a file or directory string.
Function signature:
```go
app.Static(prefix, root string, config ...Static)
```
Use the following code to serve files in a directory named `./public`:
```go
app := fiber.New()
app.Static("/", "./public")
app.Listen(":3000")
```
Now, you can load the files that are in the `./public` directory:
```bash
http://localhost:3000/hello.html
http://localhost:3000/js/jquery.js
http://localhost:3000/css/style.css
```
### Note
For more information on how to build APIs in Go with Fiber, please check out this excellent article
[on building an express-style API in Go with Fiber](https://blog.logrocket.com/express-style-api-go-fiber/).

View file

@ -0,0 +1,69 @@
---
id: route-handlers
title: Route Handlers
---
Registers a route bound to a specific [HTTP method](https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods).
```go title="Signatures"
// HTTP methods
func (app *App) Get(path string, handlers ...Handler) Router
func (app *App) Head(path string, handlers ...Handler) Router
func (app *App) Post(path string, handlers ...Handler) Router
func (app *App) Put(path string, handlers ...Handler) Router
func (app *App) Delete(path string, handlers ...Handler) Router
func (app *App) Connect(path string, handlers ...Handler) Router
func (app *App) Options(path string, handlers ...Handler) Router
func (app *App) Trace(path string, handlers ...Handler) Router
func (app *App) Patch(path string, handlers ...Handler) Router
// Add allows you to specifiy a method as value
func (app *App) Add(method, path string, handlers ...Handler) 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, handlers ...Handler) Router
```
```go title="Examples"
// Simple GET handler
app.Get("/api/list", func(c *fiber.Ctx) error {
return c.SendString("I'm a GET request!")
})
// Simple POST handler
app.Post("/api/register", func(c *fiber.Ctx) error {
return c.SendString("I'm a POST request!")
})
```
**Use** can be used for middleware packages and prefix catchers. These routes will only match the beginning of each path i.e. `/john` will match `/john/doe`, `/johnnnnn` etc
```go title="Signature"
func (app *App) Use(args ...interface{}) Router
```
```go title="Examples"
// 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()
})
```