fiber Documentation

️ Express inspired web framework written in Go

40,062 stars Go Go 1 file · ~32,856 tokens #express#expressjs#fast#fiber#flexible#framework#friendly#go
RAW Doc

1. Project Overview & Quickstart (gofiber/fiber)

File: README.md



⚙️ Installation

Fiber requires Go version 1.26 or higher to run. If you need to install or upgrade Go, visit the official Go download page. To start setting up your project, create a new directory for your project and navigate into it. Then, initialize your project with Go modules by executing the following command in your terminal:

bash
go mod init github.com/your/repo

To learn more about Go modules and how they work, you can check out the Using Go Modules blog post.

After setting up your project, you can install Fiber with the go get command:

bash
go get -u github.com/gofiber/fiber/v3

This command fetches the Fiber package and adds it to your project's dependencies, allowing you to start building your web applications with Fiber.

⚡️ Quickstart

Getting started with Fiber is easy. Here's a basic example to create a simple web server that responds with "Hello, World 👋!" on the root path. This example demonstrates initializing a new Fiber app, setting up a route, and starting the server.

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
)

func main() {
    // Initialize a new Fiber app
    app := fiber.New()

    // Define a route for the GET method on the root path '/'
    app.Get("/", func(c fiber.Ctx) error {
        // Send a string response to the client
        return c.SendString("Hello, World 👋!")
    })

    // Start the server on port 3000
    log.Fatal(app.Listen(":3000"))
}

This simple server is easy to set up and run. It introduces the core concepts of Fiber: app initialization, route definition, and starting the server. Just run this Go program, and visit http://localhost:3000 in your browser to see the message.

Zero Allocation

Fiber is optimized for high-performance, meaning values returned from fiber.Ctx are not immutable by default and will be reused across requests. As a rule of thumb, you must only use context values within the handler and must not keep any references. Once you return from the handler, any values obtained from the context will be reused in future requests. Visit our documentation to learn more.

🤖 Benchmarks

These tests are performed by TechEmpower. If you want to see all the results, please visit our Wiki.

🎯 Features

💡 Philosophy

New gophers that make the switch from Node.js to Go are dealing with a learning curve before they can start building their web applications or microservices. Fiber, as a web framework, was created with the idea of minimalism and follows the UNIX way, so that new gophers can quickly enter the world of Go with a warm and trusted welcome.

Fiber is inspired by Express, the most popular web framework on the Internet. We combined the ease of Express and raw performance of Go. If you have ever implemented a web application in Node.js (using Express or similar), then many methods and principles will seem very common to you.

We listen to our users in issues, Discord channel and all over the Internet to create a fast, flexible and friendly Go web framework for any task, deadline and developer skill! Just like Express does in the JavaScript world.

⚠️ Limitations

  • Due to Fiber's usage of unsafe, the library may not always be compatible with the latest Go version. Fiber v3 has been tested with Go version 1.26 or higher.
  • Fiber automatically adapts common net/http handler shapes when you register them on the router, and you can still use the adaptor middleware when you need to bridge entire apps or net/http middleware.

net/http compatibility

Fiber can run side by side with the standard library. The router accepts existing net/http handlers directly and even works with native fasthttp.RequestHandler callbacks, so you can plug in legacy endpoints without wrapping them manually:

go
package main

import (
    "log"
    "net/http"

    "github.com/gofiber/fiber/v3"
)

func main() {
    httpHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if _, err := w.Write([]byte("served by net/http")); err != nil {
            panic(err)
        }
    })

    app := fiber.New()
    app.Get("/", httpHandler)

    // Start the server on port 3000
    log.Fatal(app.Listen(":3000"))
}

When you need to convert entire applications or reuse net/http middleware chains, rely on the adaptor middleware. It converts handlers and middlewares in both directions and even lets you mount a Fiber app in a net/http server.

Express-style handlers

Fiber also adapts Express-style callbacks that operate on the lightweight fiber.Req and fiber.Res helper interfaces. This lets you port middleware and route handlers from Express-inspired codebases while keeping Fiber's router features:

go
// Request/response handlers (2-argument)
app.Get("/", func(req fiber.Req, res fiber.Res) error {
    return res.SendString("Hello from Express-style handlers!")
})

// Middleware with an error-returning next callback (3-argument)
app.Use(func(req fiber.Req, res fiber.Res, next func() error) error {
    if req.IP() == "192.168.1.254" {
        return res.SendStatus(fiber.StatusForbidden)
    }
    return next()
})

// Middleware with a no-arg next callback (3-argument)
app.Use(func(req fiber.Req, res fiber.Res, next func()) {
    if req.Get("X-Skip") == "true" {
        return // stop the chain without calling next
    }
    next()
})

Note: Adapted net/http handlers continue to operate with the standard-library semantics. They don't get access to fiber.Ctx features and incur the overhead of the compatibility layer, so native fiber.Handler callbacks still provide the best performance.

👀 Examples

Listed below are some of the common examples. If you want to see more code examples, please visit our Recipes repository or visit our hosted API documentation.

📖 [**Basic Routing**](https://docs.gofiber.io/#basic-routing)

go title="example"
package main

import (
    "fmt"
    "log"

    "github.com/gofiber/fiber/v3"
)

func main() {
    app := fiber.New()

    // GET /api/register
    app.Get("/api/*", func(c fiber.Ctx) error {
        msg := fmt.Sprintf("✋ %s", c.Params("*"))
        return c.SendString(msg) // => ✋ register
    })

    // GET /flights/LAX-SFO
    app.Get("/flights/:from-:to", func(c fiber.Ctx) error {
        msg := fmt.Sprintf("💸 From: %s, To: %s", c.Params("from"), c.Params("to"))
        return c.SendString(msg) // => 💸 From: LAX, To: SFO
    })

    // GET /dictionary.txt
    app.Get("/:file.:ext", func(c fiber.Ctx) error {
        msg := fmt.Sprintf("📃 %s.%s", c.Params("file"), c.Params("ext"))
        return c.SendString(msg) // => 📃 dictionary.txt
    })

    // GET /john/75
    app.Get("/:name/:age/:gender?", func(c fiber.Ctx) error {
        msg := fmt.Sprintf("👴 %s is %s years old", c.Params("name"), c.Params("age"))
        return c.SendString(msg) // => 👴 john is 75 years old
    })

    // GET /john
    app.Get("/:name", func(c fiber.Ctx) error {
        msg := fmt.Sprintf("Hello, %s 👋!", c.Params("name"))
        return c.SendString(msg) // => Hello john 👋!
    })

    log.Fatal(app.Listen(":3000"))
}

📖 [**Route Naming**](https://docs.gofiber.io/api/app#name)

go title="example"
package main

import (
    "encoding/json"
    "fmt"
    "log"

    "github.com/gofiber/fiber/v3"
)

func main() {
    app := fiber.New()

    app.Get("/api/*", func(c fiber.Ctx) error {
        msg := fmt.Sprintf("✋ %s", c.Params("*"))
        return c.SendString(msg) // => ✋ register
    }).Name("api")

    route := app.GetRoute("api")

    data, _ := json.MarshalIndent(route, "", "  ")
    fmt.Println(string(data))
    // Prints:
    // {
    //    "method": "GET",
    //    "name": "api",
    //    "path": "/api/*",
    //    "params": [
    //      "*1"
    //    ]
    // }

    log.Fatal(app.Listen(":3000"))
}

📖 [**Serving Static Files**](https://docs.gofiber.io/api/app#static)

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/fiber/v3/middleware/static"
)

func main() {
    app := fiber.New()

    // Serve static files from the "./public" directory
    app.Get("/*", static.New("./public"))
    // => http://localhost:3000/js/script.js
    // => http://localhost:3000/css/style.css

    app.Get("/prefix*", static.New("./public"))
    // => http://localhost:3000/prefix/js/script.js
    // => http://localhost:3000/prefix/css/style.css

    // Serve a single file for any unmatched routes
    app.Get("*", static.New("./public/index.html"))
    // => http://localhost:3000/any/path/shows/index.html

    log.Fatal(app.Listen(":3000"))
}

📖 [**Middleware & Next**](https://docs.gofiber.io/api/ctx#next)

go title="example"
package main

import (
    "fmt"
    "log"

    "github.com/gofiber/fiber/v3"
)

func main() {
    app := fiber.New()

    // Middleware that matches any route
    app.Use(func(c fiber.Ctx) error {
        fmt.Println("🥇 First handler")
        return c.Next()
    })

    // Middleware that matches all routes starting with /api
    app.Use("/api", func(c fiber.Ctx) error {
        fmt.Println("🥈 Second handler")
        return c.Next()
    })

    // GET /api/list
    app.Get("/api/list", func(c fiber.Ctx) error {
        fmt.Println("🥉 Last handler")
        return c.SendString("Hello, World 👋!")
    })

    log.Fatal(app.Listen(":3000"))
}

📚 Show more code examples

Views Engines

📖 Config
📖 Engines
📖 Render

Fiber defaults to the html/template when no view engine is set.

If you want to execute partials or use a different engine like amber, handlebars, mustache, or pug, etc., check out our Template package that supports multiple view engines.

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/template/pug"
)

func main() {
    // Initialize a new Fiber app with Pug template engine
    app := fiber.New(fiber.Config{
        Views: pug.New("./views", ".pug"),
    })

    // Define a route that renders the "home.pug" template
    app.Get("/", func(c fiber.Ctx) error {
        return c.Render("home", fiber.Map{
            "title": "Homepage",
            "year":  1999,
        })
    })

    log.Fatal(app.Listen(":3000"))
}

Grouping Routes into Chains

📖 Group

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
)

func middleware(c fiber.Ctx) error {
    log.Println("Middleware executed")
    return c.Next()
}

func handler(c fiber.Ctx) error {
    return c.SendString("Handler response")
}

func main() {
    app := fiber.New()

    // Root API group with middleware
    api := app.Group("/api", middleware) // /api

    // API v1 routes
    v1 := api.Group("/v1", middleware) // /api/v1
    v1.Get("/list", handler)           // /api/v1/list
    v1.Get("/user", handler)           // /api/v1/user

    // API v2 routes
    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"))
}

Middleware Logger

📖 Logger

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/fiber/v3/middleware/logger"
)

func main() {
    app := fiber.New()

    // Use Logger middleware
    app.Use(logger.New())

    // Define routes
    app.Get("/", func(c fiber.Ctx) error {
        return c.SendString("Hello, Logger!")
    })

    log.Fatal(app.Listen(":3000"))
}

Cross-Origin Resource Sharing (CORS)

📖 CORS

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/fiber/v3/middleware/cors"
)

func main() {
    app := fiber.New()

    // Use CORS middleware with default settings
    app.Use(cors.New())

    // Define routes
    app.Get("/", func(c fiber.Ctx) error {
        return c.SendString("CORS enabled!")
    })

    log.Fatal(app.Listen(":3000"))
}

Check CORS by passing any domain in Origin header:

bash
curl -H "Origin: http://example.com" --verbose http://localhost:3000

Custom 404 Response

📖 HTTP Methods

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
)

func main() {
    app := fiber.New()

    // Define routes
    app.Get("/", static.New("./public"))

    app.Get("/demo", func(c fiber.Ctx) error {
        return c.SendString("This is a demo page!")
    })

    app.Post("/register", func(c fiber.Ctx) error {
        return c.SendString("Registration successful!")
    })

    // Middleware to handle 404 Not Found
    app.Use(func(c fiber.Ctx) error {
        return c.SendStatus(fiber.StatusNotFound) // => 404 "Not Found"
    })

    log.Fatal(app.Listen(":3000"))
}

JSON Response

📖 JSON

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
)

type User struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

func main() {
    app := fiber.New()

    // Route that returns a JSON object
    app.Get("/user", func(c fiber.Ctx) error {
        return c.JSON(&User{"John", 20})
        // => {"name":"John", "age":20}
    })

    // Route that returns a JSON map
    app.Get("/json", func(c fiber.Ctx) error {
        return c.JSON(fiber.Map{
            "success": true,
            "message": "Hi John!",
        })
        // => {"success":true, "message":"Hi John!"}
    })

    log.Fatal(app.Listen(":3000"))
}

WebSocket Upgrade

📖 Websocket

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/fiber/v3/middleware/websocket"
)

func main() {
    app := fiber.New()

    // WebSocket route
    app.Get("/ws", websocket.New(func(c *websocket.Conn) {
        defer c.Close()
        for {
            // Read message from client
            mt, msg, err := c.ReadMessage()
            if err != nil {
                log.Println("read:", err)
                break
            }
            log.Printf("recv: %s", msg)

            // Write message back to client
            err = c.WriteMessage(mt, msg)
            if err != nil {
                log.Println("write:", err)
                break
            }
        }
    }))

    log.Fatal(app.Listen(":3000"))
    // Connect via WebSocket at ws://localhost:3000/ws
}

Server-Sent Events

📖 More Info

go title="example"
package main

import (
    "bufio"
    "fmt"
    "log"
    "time"

    "github.com/gofiber/fiber/v3"
    "github.com/valyala/fasthttp"
)

func main() {
    app := fiber.New()

    // Server-Sent Events route
    app.Get("/sse", func(c fiber.Ctx) error {
        c.Set("Content-Type", "text/event-stream")
        c.Set("Cache-Control", "no-cache")
        c.Set("Connection", "keep-alive")
        c.Set("Transfer-Encoding", "chunked")

        c.Context().SetBodyStreamWriter(func(w *bufio.Writer) {
            var i int
            for {
                i++
                msg := fmt.Sprintf("%d - the time is %v", i, time.Now())
                fmt.Fprintf(w, "data: Message: %s\n\n", msg)
                fmt.Println(msg)

                w.Flush()
                time.Sleep(5 * time.Second)
            }
        })

        return nil
    })

    log.Fatal(app.Listen(":3000"))
}

Recover Middleware

📖 Recover

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/fiber/v3/middleware/recover"
)

func main() {
    app := fiber.New()

    // Use Recover middleware to handle panics gracefully
    app.Use(recover.New())

    // Route that intentionally panics
    app.Get("/", func(c fiber.Ctx) error {
        panic("normally this would crash your app")
    })

    log.Fatal(app.Listen(":3000"))
}

Using Trusted Proxy

📖 Config

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
)

func main() {
    app := fiber.New(fiber.Config{
        // Configure trusted proxies - WARNING: Only trust proxies you control
        // Using TrustProxy: true with unrestricted IPs can lead to IP spoofing
        TrustProxy: true,
        TrustProxyConfig: fiber.TrustProxyConfig{
            Proxies: []string{"10.0.0.0/8", "172.16.0.0/12"}, // Example: Internal network ranges only
        },
        ProxyHeader: fiber.HeaderXForwardedFor,
    })

    // Define routes
    app.Get("/", func(c fiber.Ctx) error {
        return c.SendString("Trusted Proxy Configured!")
    })

    log.Fatal(app.Listen(":3000"))
}

🧬 Internal Middleware

Here is a list of middleware that are included within the Fiber framework.

Middleware Description
adaptor Converter for net/http handlers to/from Fiber request handlers.
basicauth Provides HTTP basic authentication. It calls the next handler for valid credentials and 401 Unauthorized for missing or invalid credentials.
cache Intercept and cache HTTP responses.
compress Compression middleware for Fiber, with support for deflate, gzip, brotli and zstd.
cors Enable cross-origin resource sharing (CORS) with various options.
csrf Protect from CSRF exploits.
earlydata Adds support for TLS 1.3's early data ("0-RTT") feature.
encryptcookie Encrypt middleware which encrypts cookie values.
envvar Expose environment variables with providing an optional config.
etag Allows for caches to be more efficient and save bandwidth, as a web server does not need to resend a full response if the content has not changed.
expvar Serves via its HTTP server runtime exposed variables in the JSON format.
favicon Ignore favicon from logs or serve from memory if a file path is provided.
healthcheck Liveness and Readiness probes for Fiber.
helmet Helps secure your apps by setting various HTTP headers.
hostauthorization Validates the Host header against a configurable allowlist, protecting against DNS rebinding attacks.
idempotency Allows for fault-tolerant APIs where duplicate requests do not erroneously cause the same action performed multiple times on the server-side.
keyauth Adds support for key based authentication.
limiter Adds Rate-limiting support to Fiber. Use to limit repeated requests to public APIs and/or endpoints such as password reset.
logger HTTP request/response logger.
paginate Extracts pagination parameters from query strings. Supports page-based, offset-based, and cursor-based pagination with multi-field sorting.
pprof Serves runtime profiling data in pprof format.
proxy Allows you to proxy requests to multiple servers.
recover Recovers from panics anywhere in the stack chain and handles the control to the centralized ErrorHandler.
redirect Redirect middleware.
requestid Adds a request ID to every request.
responsetime Measures request handling duration and writes it to a configurable response header.
rewrite Rewrites the URL path based on provided rules. It can be helpful for backward compatibility or just creating cleaner and more descriptive links.
session Session middleware. NOTE: This middleware uses our Storage package.
skip Skip middleware that skips a wrapped handler if a predicate is true.
static Static middleware for Fiber that serves static files such as images, CSS, and JavaScript.
timeout Adds a max time for a request and forwards to ErrorHandler if it is exceeded.

🧬 External Middleware

List of externally hosted middleware modules and maintained by the Fiber team.

Middleware Description
contrib Third-party middlewares
storage Premade storage drivers that implement the Storage interface, designed to be used with various Fiber middlewares.
template This package contains 9 template engines that can be used with Fiber.

🕶️ Awesome List

For more articles, middlewares, examples, or tools, check our awesome list.

👍 Contribute

If you want to say Thank You and/or support the active development of Fiber:

  1. Add a GitHub Star to the project.
  2. Tweet about the project on your 𝕏 (Twitter).
  3. Write a review or tutorial on Medium, Dev.to or your personal blog.
  4. Support the project by becoming a GitHub Sponsor.

💻 Development

To ensure your contributions are ready for a Pull Request, please use the following Makefile commands. These tools help maintain code quality and consistency.

  • make help: Display available commands.
  • make audit: Conduct quality checks.
  • make benchmark: Benchmark code performance.
  • make coverage: Generate test coverage report.
  • make format: Automatically format code.
  • make lint: Run lint checks.
  • make test: Execute all tests.
  • make tidy: Tidy dependencies.

Run these commands to ensure your code adheres to project standards and best practices.

☕ Supporters

Fiber is an open-source project that runs on donations to pay the bills, e.g., our domain name, GitBook, Netlify, and serverless hosting. If you want to support Fiber, please sponsor the organization via ⭐ GitHub Sponsors.

📅 Monthly Sponsors

🔥 Fiber Guardian
☕ Fiber Supporter
🪴 Fiber Friend

🎁 One-time Sponsors

🚀 Fiber Hero
🪴 Fiber Friend

💻 Code Contributors

⭐️ Stargazers

🧾 License

Copyright (c) 2019-present Fenny and Contributors. Fiber is free and open-source software licensed under the MIT License. Official logo was created by Vic Shóstak and distributed under Creative Commons license (CC BY-SA 4.0 International).


File: addon/retry/README.md

Retry Addon

Retry addon for Fiber designed to apply retry mechanism for unsuccessful network
operations. This addon uses an exponential backoff algorithm with jitter. It calls the function multiple times and tries
to make it successful. If all calls are failed, then, it returns an error. It adds a jitter at each retry step because adding
a jitter is a way to break synchronization across the client and avoid collision.

Table of Contents

Signatures

go
func NewExponentialBackoff(config ...retry.Config) *retry.ExponentialBackoff

Examples

go
package main

import (
    "fmt"

    "github.com/gofiber/fiber/v3/addon/retry"
    "github.com/gofiber/fiber/v3/client"
)

func main() {
    expBackoff := retry.NewExponentialBackoff(retry.Config{})

    // Local variables that will be used inside of Retry
    var resp *client.Response
    var err error

    // Retry a network request and return an error to signify to try again
    err = expBackoff.Retry(func() error {
        client := client.New()
        resp, err = client.Get("https://gofiber.io")
        if err != nil {
            return fmt.Errorf("GET gofiber.io failed: %w", err)
        }
        if resp.StatusCode() != 200 {
            return fmt.Errorf("GET gofiber.io did not return OK 200")
        }
        return nil
    })

    // If all retries failed, panic
    if err != nil {
        panic(err)
    }
    fmt.Printf("GET gofiber.io succeeded with status code %d\n", resp.StatusCode())
}

Default Config

go
retry.NewExponentialBackoff()

Custom Config

go
retry.NewExponentialBackoff(retry.Config{
    InitialInterval: 2 * time.Second,
    MaxBackoffTime:  64 * time.Second,
    Multiplier:      2.0,
    MaxRetryCount:   15,
})

Config

go
// Config defines the config for addon.
type Config struct {
    // InitialInterval defines the initial time interval for backoff algorithm.
    //
    // Optional. Default: 1 * time.Second
    InitialInterval time.Duration

    // MaxBackoffTime defines maximum time duration for backoff algorithm. When
    // the algorithm is reached this time, rest of the retries will be maximum
    // 32 seconds.
    //
    // Optional. Default: 32 * time.Second
    MaxBackoffTime time.Duration

    // Multiplier defines multiplier number of the backoff algorithm.
    //
    // Optional. Default: 2.0
    Multiplier float64

    // MaxRetryCount defines maximum retry count for the backoff algorithm.
    //
    // Optional. Default: 10
    MaxRetryCount int
}

Default Config Example

go
// DefaultConfig is the default config for retry.
var DefaultConfig = Config{
    InitialInterval: 1 * time.Second,
    MaxBackoffTime:  32 * time.Second,
    Multiplier:      2.0,
    MaxRetryCount:   10,
    currentInterval: 1 * time.Second,
}

Every Retry call starts over at InitialInterval and keeps its backoff state to itself, so one ExponentialBackoff can be shared by concurrent callers.


File: binder/README.md

Fiber Binders

Binder is a new request/response binding feature for Fiber introduced in Fiber v3. It replaces the old Fiber parsers and offers enhanced capabilities such as custom binder registration, struct validation, support for map[string]string, map[string][]string, and more. Binder replaces the following components:

  • BodyParser
  • ParamsParser
  • GetReqHeaders
  • GetRespHeaders
  • AllParams
  • QueryParser
  • ReqHeaderParser

Default Binders

Fiber provides several default binders out of the box:

Guides

Binding into a Struct

Fiber supports binding request data directly into a struct using gofiber/schema. Here's an example:

go
// Field names must start with an uppercase letter
type Person struct {
    Name string `json:"name" xml:"name" form:"name"`
    Pass string `json:"pass" xml:"pass" form:"pass"`
}

app.Post("/", func(c fiber.Ctx) error {
    p := new(Person)

    if err := c.Bind().Body(p); err != nil {
        return err
    }

    log.Println(p.Name) // Output: john
    log.Println(p.Pass) // Output: doe

    // Additional logic...
})

// Run tests with the following curl commands:

// JSON
curl -X POST -H "Content-Type: application/json" --data "{\"name\":\"john\",\"pass\":\"doe\"}" localhost:3000

// XML
curl -X POST -H "Content-Type: application/xml" --data "<login><name>john</name>doe</login>" localhost:3000

// URL-Encoded Form
curl -X POST -H "Content-Type: application/x-www-form-urlencoded" --data "name=john&pass=doe" localhost:3000

// Multipart Form
curl -X POST -F name=john -F pass=doe http://localhost:3000

// Query Parameters
curl -X POST "http://localhost:3000/?name=john&pass=doe"

Binding into a Map

Fiber allows binding request data into a map[string]string or map[string][]string. Here's an example:

go
app.Get("/", func(c fiber.Ctx) error {
    params := make(map[string][]string)

    if err := c.Bind().Query(params); err != nil {
        return err
    }

    log.Println(params["name"])     // Output: [john]
    log.Println(params["pass"])     // Output: [doe]
    log.Println(params["products"]) // Output: [shoe hat]

    // Additional logic...
    return nil
})

// Run tests with the following curl command:

curl "http://localhost:3000/?name=john&pass=doe&products=shoe&products=hat"

Automatic Error Handling with `WithAutoHandling`

By default, Fiber returns binder errors directly. To handle errors automatically and return a 400 Bad Request status, use the WithAutoHandling() method.

Example:

go
// Field names must start with an uppercase letter
type Person struct {
    Name string `json:"name,required"`
    Pass string `json:"pass"`
}

app.Get("/", func(c fiber.Ctx) error {
    p := new(Person)

    if err := c.Bind().WithAutoHandling().JSON(p); err != nil {
        return err 
        // Automatically returns status code 400
        // Response: Bad request: name is empty
    }

    // Additional logic...
    return nil
})

// Run tests with the following curl command:

curl -X GET -H "Content-Type: application/json" --data "{\"pass\":\"doe\"}" localhost:3000

Defining a Custom Binder

Fiber maintains a minimal codebase by not including every possible binder. If you need to use a custom binder, you can easily register and utilize it. Here's an example of creating a toml binder.

go
type Person struct {
    Name string `toml:"name"`
    Pass string `toml:"pass"`
}

type tomlBinding struct{}

func (b *tomlBinding) Name() string {
    return "toml"
}

func (b *tomlBinding) MIMETypes() []string {
    return []string{"application/toml"}
}

func (b *tomlBinding) Parse(c fiber.Ctx, out any) error {
    return toml.Unmarshal(c.Body(), out)
}

func main() {
    app := fiber.New()
    app.RegisterCustomBinder(&tomlBinding{})

    app.Get("/", func(c fiber.Ctx) error {
        out := new(Person)
        if err := c.Bind().Body(out); err != nil {
            return err
        }

        // Alternatively, specify the custom binder:
        // if err := c.Bind().Custom("toml", out); err != nil {
        //     return err
        // }

        return c.SendString(out.Pass) // Output: test
    })

    app.Listen(":3000")
}

// Run tests with the following curl command:

curl -X GET -H "Content-Type: application/toml" --data "name = 'bar'
pass = 'test'" localhost:3000

Defining a Custom Validator

All Fiber binders support struct validation if a validator is defined in the configuration. You can create your own validator or use existing ones like go-playground/validator or go-ozzo/ozzo-validation. Here's an example of a simple custom validator:

go
type Query struct {
    Name string `query:"name"`
}

type structValidator struct{}

func (v *structValidator) Engine() any {
    return nil // Implement if using an external validation engine
}

func (v *structValidator) ValidateStruct(out any) error {
    data := reflect.ValueOf(out).Elem().Interface()
    query := data.(Query)

    if query.Name != "john" {
        return errors.New("you should have entered the correct name!")
    }

    return nil
}

func main() {
    app := fiber.New(fiber.Config{
        StructValidator: &structValidator{},
    })

    app.Get("/", func(c fiber.Ctx) error {
        out := new(Query)
        if err := c.Bind().Query(out); err != nil {
            return err // Returns: you should have entered the correct name!
        }
        return c.SendString(out.Name)
    })

    app.Listen(":3000")
}

// Run tests with the following curl command:

curl "http://localhost:3000/?name=efe"

File: client/README.md

Fiber Client

Features

The characteristics have not yet been written.

  • GET, POST, PUT, DELETE, HEAD, PATCH, OPTIONS, etc.
  • Simple and chainable methods for settings and request
  • Request Body can be string, []byte, map, slice
    • Auto detects Content-Type
    • Buffer processing for files
    • Native *fasthttp.Request instance can be accessed during middleware and request execution via Request.RawRequest
    • Request Body can be read multiple time via Request.RawRequest.GetBody()
  • Response object gives you more possibility
    • Access as []byte by response.Body() or access as string by response.String()
  • Automatic marshal and unmarshal for JSON and XML content type
    • Default is JSON, if you supply struct/map without header Content-Type
    • For auto-unmarshal, refer to -
      • Success scenario Request.SetResult() and Response.Result().
      • Error scenario Request.SetError() and Response.Error().
      • Supports RFC7807 - application/problem+json & application/problem+xml
    • Provide an option to override JSON Marshal/Unmarshal and XML Marshal/Unmarshal

Usage

The following samples will assist you to become as comfortable as possible with Fiber Client library.

go
// Import Fiber Client into your code and refer it as `client`.
import "github.com/gofiber/fiber/client"

Simple GET


File: docs/guide/error-handling.md


id: error-handling title: 🐛 Error Handling Fiber supports centralized error handling: handlers return errors so you can log them or send a custom HTTP response to the client. sidebar_position: 4

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Catching Errors

Return errors from route handlers and middleware so Fiber can handle them centrally.

go
app.Get("/", func(c fiber.Ctx) error {
    // Pass error to Fiber
    return c.SendFile("file-does-not-exist")
})

Fiber does not recover from panics by default. Add the Recover middleware to catch panics in any handler:

go title="example"
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/fiber/v3/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"))
}

Use fiber.NewError() to create an error with a status code. If you omit the message, Fiber uses the standard status text (for example, 404 becomes 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 ships with a default error handler that sends 500 Internal Server Error for generic errors. If the error is a fiber.Error, the response uses the embedded 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
    var e *fiber.Error
    matched := errors.As(err, &e)
    if matched && e != nil {
        code = e.Code
    }
    message := http.StatusText(code)
    if err != nil && !(matched && e == nil) {
        message = err.Error()
    }

    // 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(message)
}

Custom Error Handler

Set a custom error handler in fiber.Config when creating a new app.

The default handler covers most cases, but a custom handler lets you react to specific error types—for example, by logging to a service or sending a tailored JSON or HTML 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) && e != nil {
            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 and Express frameworks for inspiring parts of this error-handling approach.


File: docs/guide/faster-fiber.md


id: faster-fiber title: ⚡ Make Fiber Faster sidebar_position: 11

Custom JSON Encoder/Decoder

Fiber defaults to the standard encoding/json for stability and reliability. If you need more speed, consider these libraries:

go title="example"
package main

import "github.com/gofiber/fiber/v3"
import "github.com/goccy/go-json"

func main() {
    app := fiber.New(fiber.Config{
        JSONEncoder: json.Marshal,
        JSONDecoder: json.Unmarshal,
    })

    // ...
}

References

Alternative Regex Engines for `regex()` Constraints

Fiber route patterns still do not support general regex routes, but you can swap
the compiler used by regex() parameter constraints through
Config.RegexHandler. This lets you try
high-performance engines such as
coregex on the matching path.

Configure `RegexHandler`

Set RegexHandler to the compile function you want Fiber to use for regex()
constraints.

go title="example"
package main

import (
    "github.com/coregx/coregex"
    "github.com/gofiber/fiber/v3"
)

func main() {
    app := fiber.New(fiber.Config{
        RegexHandler: coregex.MustCompile,
    })

    app.Get("/api/:id<regex(\\d+)>", func(c fiber.Ctx) error {
        return c.SendString("ID: " + c.Params("id"))
    })
}

You can also set it explicitly to the standard library default:

go title="example"
package main

import (
    "regexp"

    "github.com/gofiber/fiber/v3"
)

func main() {
    app := fiber.New(fiber.Config{
        RegexHandler: regexp.MustCompile,
    })

    _ = app
}

Notes

  • RegexHandler only affects regex() parameter constraints
  • invalid patterns still panic during route registration because Fiber uses
    MustCompile-style semantics
  • Fiber may invoke RegexHandler more than once per route while parsing raw and
    normalized route patterns during registration
  • compiled matchers are reused across requests, so custom matchers must be safe
    for concurrent use
  • Zero Allocation: why Ctx values are reused across requests and how to copy them safely
  • Benchmarks: how Fiber compares to other frameworks

File: docs/guide/grouping.md


id: grouping title: 🎭 Grouping sidebar_position: 2

:::info
Grouping works like Express.js. Groups are virtual; routes are flattened with the group's prefix and executed in declaration order, mirroring Express.js.
:::

Paths

Groups can use path prefixes to organize related routes.

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"))
}

:::note
Group prefixes follow the same slash-boundary rule as app.Use. A prefix must either match the full path or stop at a /, so /api applies to /api and /api/v1 but not /apiv1. Parameter markers (for example :id, :id?, *, and +) are processed before checking the boundary.
:::

Groups can also include 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
Accessing /api, /v1, or /v2 directly returns a 404, so add error handlers as needed.
:::

Group Handlers

Group handlers can act as routing paths but must call Next to continue the flow.

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"))
}

Route

Route groups routes under a common prefix declared inside a single callback, with an optional name prefix. It is shorthand for nesting with Group.

go
app.Route("/api/v1", func(r fiber.Router) {
    r.Get("/users", handler).Name("users")   // /api/v1/users  (name: v1.users)
    r.Post("/users", handler).Name("create") // /api/v1/users  (name: v1.create)
}, "v1.")

RouteChain

When several HTTP methods share the same path, RouteChain lets you declare the path once and chain the verb handlers. An All in the chain runs before the verb handlers on that path, acting as route-specific middleware.

go
app.RouteChain("/events").
    All(func(c fiber.Ctx) error { return c.Next() }). // route-local middleware
    Get(func(c fiber.Ctx) error { return c.SendString("GET /events") }).
    Post(func(c fiber.Ctx) error { return c.SendString("POST /events") })

:::note
Within a chain, All registers prefix-matched middleware (like app.Use), not the exact-path App.All, so it also runs for sub-paths of the chain path.
:::


File: docs/guide/routing.md


id: routing title: 🔌 Routing Routing refers to how an application's endpoints (URIs) respond to client requests. sidebar_position: 1 toc_max_heading_level: 4

import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
import RoutingHandler from './../partials/routing/handler.md';
import RoutingUse from './../partials/routing/use.md';
import RoutingHandlerTypes from './../partials/routing/handler-types.md';
import RouteAnatomy from '@site/src/components/route-anatomy';
import MiddlewareVisualizer from '@site/src/components/middleware-visualizer';

Anatomy of a route

A route ties together an HTTP method, a path, and one or more handlers. Hover or click any colored part to jump to the section that explains it:

Get is the routing method, "/users/:id" is the route path (the resource, in REST terms) with :id a route parameter, and func(c fiber.Ctx) error is the handler (or middleware) run when the route matches.

Want to see matching happen? Fire requests at your own route table in the interactive Route Matcher.

Route Handlers

Here is a complete, runnable app for context:

go title="a minimal fiber app"
package main

import "github.com/gofiber/fiber/v3"

func main() {
    app := fiber.New()

    app.Get("/", func(c fiber.Ctx) error {
        return c.SendString("Hello, World!")
    })

    app.Listen(":3000")
}

In the shorter examples throughout this guide, app is the *fiber.App returned by fiber.New(), and handler/middleware stand in for any func(c fiber.Ctx) error. Snippets that call fmt.Println or fmt.Fprintf also need import "fmt".

Beyond the native func(fiber.Ctx) forms, Fiber also adapts Express-style, net/http, and fasthttp handlers. See Handler types at the end of this guide for the full list of supported shapes.

Get vs Use vs All

Get (and the other method helpers like Post and Put) match a single HTTP method at an exact path. All matches an exact path across every HTTP method. Use registers middleware that matches by prefix and runs in declaration order, calling c.Next() to continue the chain.

go
app.Get("/users", func(c fiber.Ctx) error {
    return c.SendString("GET /users")
})

// GET    /users      -> "GET /users"
// POST   /users      -> 405 Method Not Allowed
// GET    /users/42   -> 404 Not Found  (exact match only)
go
app.All("/ping", func(c fiber.Ctx) error {
    return c.SendString(c.Method() + " /ping")
})

// GET    /ping        -> "GET /ping"
// POST   /ping        -> "POST /ping"
// DELETE /ping        -> "DELETE /ping"
// GET    /ping/extra  -> 404 Not Found  (still exact path)
go
// Empty Use: no path -> matches every request, any method, any path
app.Use(func(c fiber.Ctx) error {
    c.Set("X-Powered-By", "Fiber")
    return c.Next()
})

// Prefixed Use: matches the prefix and anything below a slash boundary
app.Use("/api", func(c fiber.Ctx) error {
    return c.Next()
})

// The empty Use above runs for ALL of these. The notes below show which
// requests ALSO match the prefixed "/api" Use:
// /api        -> also matches "/api" Use   (exact prefix)
// /api/users  -> also matches "/api" Use   (slash boundary)
// /apiv2      -> empty Use only             (no slash boundary)
// /anything   -> empty Use only

Multiple handlers that match the same request run in the order you declare them. Each must call c.Next() to pass control to the next; if one returns without calling it, the rest of the chain is skipped.

go
app.Use("/api", func(c fiber.Ctx) error {
    fmt.Println("1: auth check")
    return c.Next()
})

app.Use("/api", func(c fiber.Ctx) error {
    fmt.Println("2: logging")
    return c.Next()
})

app.Get("/api/users", func(c fiber.Ctx) error {
    fmt.Println("3: handler")
    return c.SendString("users")
})

// GET /api/users prints, in order:
//   1: auth check
//   2: logging
//   3: handler

Attach several handlers in a single registration: list the route-specific middleware before the business handler.

go
app.Get("/users/:id",
    func(c fiber.Ctx) error { // 1: require authentication
        if c.Get("Authorization") == "" {
            return c.SendStatus(fiber.StatusUnauthorized) // returns without c.Next(): stops here
        }
        return c.Next()
    },
    func(c fiber.Ctx) error { // 2: stash data for downstream handlers
        c.Locals("userID", c.Params("id"))
        return c.Next()
    },
    func(c fiber.Ctx) error { // 3: business handler reads the stashed value
        return c.SendString("user " + c.Locals("userID").(string))
    },
)

// GET /users/42 (no Authorization header) -> 401, handlers 2 and 3 never run
// GET /users/42 (with Authorization)      -> "user 42"
Helper Methods matched Path matching Typical use
Get/Post/… one exact a specific endpoint
All every method exact one path, any verb
Use every method prefix (slash boundary); all paths if none given middleware, mounting sub-apps

A path that exists only for a different method returns 405 Method Not Allowed; a path that matches no route at all (including one rejected by a constraint) returns 404 Not Found.

Paths

A route path paired with an HTTP method defines an endpoint. It can be a plain string or a pattern.

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")
})

The order in which you declare routes matters: like Express.js, routes are matched in registration order (first match wins), so declare more specific paths before those that contain parameters. Note that method helpers such as Get match the exact path only.

:::info
Place routes with variable parameters after fixed paths to avoid unintended matches.
:::

Path normalization

Before a request is matched, Fiber normalizes its path as RFC 3986 Section 6.2.2 describes:

  • Percent-encoded unreserved characters (letters, digits, -, ., _ and ~) are decoded, so /%70rivate is matched as /private. Every other escape stays encoded with uppercase hex digits, so an encoded slash (%2F) never splits a segment and /a%2fb is matched as /a%2Fb. With UnescapePath enabled, every escape is decoded instead.
  • . and .. segments are resolved, so /static/x/../private and /static/./private are both matched as /static/private. A .. never climbs above the root. Empty segments are kept: /static//private is a different path from /static/private.

Middleware mounted on a prefix therefore sees these spellings of a path under it, and c.Path() returns the normalized path. Decoding happens exactly once: /%2570rivate is matched as /%2570rivate by default and as /%70rivate with UnescapePath, and neither becomes /private. c.OriginalURL() still returns the request target as the client sent it.

Parameters

Route parameters are dynamic segments in a path, either named or unnamed, used to capture values from the URL. Retrieve them with the Params function using the parameter name or, for unnamed parameters, the wildcard (*) or plus (+) symbol with an index.

The characters :, +, and * introduce parameters. Append ? to a named segment to make it optional. + is a greedy, required wildcard (it must match at least one character); * is a greedy, optional wildcard (it can match nothing).

go
// Named 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, required (matches at least one character)
app.Get("/user/+", func(c fiber.Ctx) error {
    return c.SendString(c.Params("+"))
})

// Optional named parameter
app.Get("/user/:name?", func(c fiber.Ctx) error {
    return c.SendString(c.Params("name"))
})

// Wildcard - greedy, optional (may match nothing)
app.Get("/user/*", func(c fiber.Ctx) error {
    return c.SendString(c.Params("*"))
})

The hyphen (-), dot (.), and colon (:) are treated literally between parameters, so you can combine them with route parameters. Fiber's router detects when these characters belong to the literal path.

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
})

// 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
})

// 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
})

Escape special parameter characters with \\ to treat them literally. This is useful for custom methods like those in the Google API Design Guide. Wrap routes in backticks to keep escape sequences clear.

go
// Matches "/v1/some/resource/name:customVerb" because the colon is escaped
app.Get(`/v1/some/resource/name\:customVerb`, func(c fiber.Ctx) error {
    return c.SendString("Hello, Community")
})

// Matches only the literal path "/*"; an escaped star is not the catch-all route
app.Get(`/\*`, func(c fiber.Ctx) error {
    return c.SendString("literal star")
})

You can chain multiple named or unnamed parameters, including wildcard and plus segments, within a single segment.

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)

:::info
Fiber lets multiple parameters share a single path segment, unlike routers such as Express, Gin, and Echo where :param always consumes a whole segment. When named parameters are adjacent with no literal separator between them, the router cannot know where one parameter ends and the next begins: there is no delimiter in the pattern to split on.

To keep matching deterministic, Fiber assigns every adjacent named parameter except the last a fixed length of one character, and the last parameter takes the remainder of the segment (up to the next delimiter or end of path). This is why /:sign:param against /@v1 yields sign=@ and param=v1, not sign=@v and param=1.

If you need a multi-character split, put a literal delimiter between parameters, for example /:sign-:param matching /@v-1.
:::

When a route has several wildcard (*) or plus (+) segments, retrieve them positionally with a 1-based index matching the symbol: c.Params("*1") and c.Params("*2") for wildcards, c.Params("+1") and c.Params("+2") for plus segments. A single wildcard or plus is just c.Params("*") or c.Params("+").

Fiber's routing is inspired by Express but intentionally omits regex route patterns due to their performance cost. To validate a parameter against a regular expression, use the regex() constraint described below.

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 introduced in v2.37.0 and inspired by .NET Core.

:::caution
Constraints are matching rules, not input validation: if a value fails a constraint, the route simply does not match and Fiber returns 404 Not Found.
:::

Constraint Example Example matches
int :id 123456789, -123456789
bool :active true,false
guid :id<guid> CD2C1638-1638-72D5-1638-DEADBEEF1638
float :weight<float> 1.234, -1001.01e8, 3.14
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)

Constraint names and arguments are always taken from the pattern as written, even with the default case-insensitive routing: :code<regex([A-Z]{2})> keeps matching uppercase codes only, a datetime layout keeps its T and Z, and a custom constraint registered under a mixed-case name is found.

Examples

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
// Not Found

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
// Not Found

// curl -X GET http://localhost:3000/1
// Not Found

// curl -X GET http://localhost:3000/250
// 250

Fiber precompiles the regex when registering routes, so the pattern is matched (not recompiled) on each request.

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
// Not Found

// curl -X GET http://localhost:3000/test
// Not Found

// curl -X GET http://localhost:3000/2022-08-27
// 2022-08-27

:::caution
When using the datetime constraint, prefix routing characters (*, +, ?, :, /, <, >, ;, (, )) with \\ to avoid misparsing.
:::

Optional Parameter Example

You can impose constraints on optional parameters as well.

go
app.Get("/:test?", 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
// Not Found

Custom Constraint

Custom constraints can be added to Fiber using the app.RegisterCustomConstraint method. Your constraints have to be compatible with the CustomConstraint interface.

:::caution
Attention, custom constraints can now override built-in constraints. If a custom constraint has the same name as a built-in constraint, the custom constraint will be used instead. This allows for more flexibility in defining route parameter constraints.
:::

Add external constraints when you need stricter rules, such as verifying that a parameter is a valid ULID.

go
// CustomConstraint is an interface for custom constraints
type CustomConstraint interface {
    // Name returns the name of the constraint.
    // This name is used in the constraint matching.
    Name() string

    // Execute executes the constraint.
    // It returns true if the constraint is matched and right.
    // param is the parameter value to check.
    // args are the constraint arguments.
    Execute(param string, args ...string) bool
}

You can check the example below:

go
type UlidConstraint struct {
    fiber.CustomConstraint
}

func (*UlidConstraint) Name() string {
    return "ulid"
}

func (*UlidConstraint) Execute(param string, args ...string) bool {
    _, err := ulid.Parse(param)
    return err == nil
}

func main() {
    app := fiber.New()
    app.RegisterCustomConstraint(&UlidConstraint{})

    app.Get("/login/:id", func(c fiber.Ctx) error {
        return c.SendString("...")
    })

    app.Listen(":3000")

    // /login/01HK7H9ZE5BFMK348CPYP14S0Z -> 200
    // /login/12345 -> 404
}

ConstraintHandler Interface

In addition to the CustomConstraint interface, Fiber v3 provides a more powerful ConstraintHandler interface that supports precomputation at route registration time. All built-in constraints implement this interface.

go
// ConstraintHandler is the interface that all constraints must implement.
type ConstraintHandler interface {
    // Name returns the constraint identifier used in route patterns.
    Name() string

    // Execute validates a request parameter value against the constraint.
    // data contains the pre-typed constraint data produced by Analyze().
    Execute(param string, data []any) bool
}

Optionally, a constraint can implement ConstraintAnalyzer to preprocess data at registration time, avoiding repeated parsing on every request:

go
// ConstraintAnalyzer is an optional interface for registration-time precomputation.
type ConstraintAnalyzer interface {
    // Analyze preprocesses constraint data at route registration time.
    // Returns pre-typed values that will be stored in Constraint.Data.
    Analyze(args []string) ([]any, error)
}

:::note
Existing CustomConstraint implementations continue to work unchanged. They are automatically wrapped to satisfy ConstraintHandler. Custom constraints that also implement ConstraintAnalyzer will have their Analyze method called at registration time.
:::

:::tip Try it live
Test route patterns, registration order, and constraints against real requests in the interactive Route Matcher tool.
:::

Middleware

Functions that are designed to make changes to the request or response are called middleware functions. c.Next() passes control to the next handler in the matched chain (middleware or route handler); if a handler returns without calling it, the remaining handlers are skipped.

go title="example of a middleware function"
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!")
})

Once a route matches, its handlers run as one chain in registration order; each handler decides with c.Next() whether the rest of the chain runs. Step through the chain yourself, including what happens when a middleware short-circuits instead of calling c.Next():

See Get vs Use vs All for how Use prefix matching differs from exact route matching, and how multiple handlers run in order.

Use

Adding or removing routes at runtime

:::caution
Defining all routes before the app starts is strongly recommended. You can still change them at runtime with RebuildTree, RemoveRoute, RemoveRouteByName, and RemoveRouteFunc, but these operations are not thread-safe and are performance-intensive, so use them sparingly and only in development.
:::

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.

Route

Route is shorthand for Group: it scopes a set of routes under a common prefix declared inside a single callback, with an optional name prefix.

go
app.Route("/api/v1", func(r fiber.Router) {
    r.Get("/users", handler).Name("users")   // /api/v1/users  (name: v1.users)
    r.Post("/users", handler).Name("create") // /api/v1/users  (name: v1.create)
}, "v1.")

RouteChain

When several HTTP methods share the same path, RouteChain lets you declare the path once and chain the verb handlers. An All in the chain runs before the verb handlers on that path, acting as route-specific middleware.

go
app.RouteChain("/events").
    All(func(c fiber.Ctx) error { return c.Next() }). // route-local middleware
    Get(func(c fiber.Ctx) error { return c.SendString("GET /events") }).
    Post(func(c fiber.Ctx) error { return c.SendString("POST /events") })

:::note
Within a chain, All registers prefix-matched middleware (like Use), not the exact-path App.All, so it also runs for sub-paths of the chain path.
:::

Pick the helper that fits: a single endpoint uses Get/Post/…; a fixed set of methods on one path uses Add; one path with many methods (fluently) uses RouteChain; many paths under a shared prefix use Group or Route.

Automatic HEAD routes

Fiber automatically registers a HEAD route for every GET route you add. The generated handler chain mirrors the GET chain, so HEAD requests reuse middleware, status codes, and headers while the response body is suppressed. This covers the routes of mounted sub-apps at any nesting depth, and routes added at runtime get their HEAD companion when RebuildTree publishes them.

go title="get handlers automatically expose head"
app := fiber.New()

app.Get("/users/:id", func(c fiber.Ctx) error {
    c.Set("X-User", c.Params("id"))
    return c.SendStatus(fiber.StatusOK)
})

// HEAD /users/:id now returns the same headers and status without a body.

You can still register dedicated HEAD handlers, even with auto-registration enabled, and Fiber replaces the generated route so your implementation wins:

go title="override the generated head handler"
app.Head("/users/:id", func(c fiber.Ctx) error {
    return c.SendStatus(fiber.StatusNoContent)
})

To opt out globally, start the app with DisableHeadAutoRegister:

go title="disable automatic head registration"
handler := func(c fiber.Ctx) error {
    c.Set("X-User", c.Params("id"))
    return c.SendStatus(fiber.StatusOK)
}

app := fiber.New(fiber.Config{DisableHeadAutoRegister: true})
app.Get("/users/:id", handler) // HEAD /users/:id now returns 405 unless you add it manually.

Auto-generated HEAD routes participate in every router scope, including Group hierarchies, mounted sub-apps, parameterized and wildcard paths, and static file helpers. They also appear in route listings such as app.Stack() so tooling sees both the GET and HEAD entries.

Handler types


File: docs/guide/utils.md


id: utils title: 🧰 Utils sidebar_position: 9 toc_max_heading_level: 4

Generics

Convert

Converts a string to a specific type while handling errors and optional defaults.
It wraps conversion and fallback logic to keep your code clean and consistent.

go title="signature"
func Convert[T any](value string, converter func(string) (T, error), defaultValue ...T) (T, error)
go title="example"
// GET http://example.com/id/bb70ab33-d455-4a03-8d78-d3c1dacae9ff
app.Get("/id/:id", func(c fiber.Ctx) error {
    fiber.Convert(c.Params("id"), uuid.Parse)                   // UUID(bb70ab33-d455-4a03-8d78-d3c1dacae9ff), nil
})

// GET http://example.com/search?id=65f6f54221fb90e6a6b76db7
app.Get("/search", func(c fiber.Ctx) error {
    fiber.Convert(c.Query("id"), mongo.ParseObjectID)           // objectid(65f6f54221fb90e6a6b76db7), nil
    fiber.Convert(c.Query("id"), uuid.Parse)                    // uuid.Nil, error(cannot parse given uuid)
    fiber.Convert(c.Query("id"), uuid.Parse, mongo.NewObjectID) // new object id generated and return nil as error.
    return nil
})

// ...

GetReqHeader

Retrieves an HTTP request header as a specific type using generics.

go title="signature"
func GetReqHeader[V GenericType](c Ctx, key string, defaultValue ...V) V
go title="example"
app.Get("/search", func(c fiber.Ctx) error {
    // curl -X GET http://example.com/search -H "X-Request-ID: 12345" -H "X-Request-Name: John"
    fiber.GetReqHeader[int](c, "X-Request-ID")               // => returns 12345 as integer.
    fiber.GetReqHeader[string](c, "X-Request-Name")          // => returns "John" as string.
    fiber.GetReqHeader[string](c, "unknownParam", "default") // => returns "default" as string.
    // ...
})

Locals

Reads or writes local values in the request context using generics.

go title="signature"
// Set a value
func Locals[V any](c Ctx, key any, value ...V) V
// Get a value
func Locals[V any](c Ctx, key any) V
go title="example"
app.Use("/user/:user/:id", func(c fiber.Ctx) error {
    // set local values
    fiber.Locals[string](c, "user", "john")
    fiber.Locals[int](c, "id", 25)
    // ...
    
    return c.Next()
})


app.Get("/user/*", func(c fiber.Ctx) error {
    // get local values
    name := fiber.Locals[string](c, "user") // john
    age := fiber.Locals[int](c, "id")       // 25
    // ...
})

Params

Retrieves route parameters as a specific type.

go title="signature"
func Params[V GenericType](c Ctx, key string, defaultValue ...V) V
go title="example"
app.Get("/user/:user/:id", func(c fiber.Ctx) error {
    // http://example.com/user/john/25
    fiber.Params[int](c, "id")               // => returns 25 as integer.
    fiber.Params[int](c, "unknownParam", 99) // => returns the default 99 as integer.
    // ...
    return c.SendString("Hello, " + fiber.Params[string](c, "user"))
})

Query

Retrieves query parameters as a specific type.

go title="signature"
func Query[V GenericType](c Ctx, key string, defaultValue ...V) V
go title="example"
app.Get("/search", func(c fiber.Ctx) error {
    // http://example.com/search?name=john&age=25
    fiber.Query[string](c, "name")                    // => returns "john"
    fiber.Query[int](c, "age")                        // => returns 25 as integer.
    fiber.Query[string](c, "unknownParam", "default") // => returns "default" as string.
    // ...
})

RoutePatternMatch

Checks whether a given path matches a Fiber route pattern. Useful for testing
patterns without registering them. Patterns may contain parameters, wildcards
and optional segments. An optional Config allows control over case sensitivity
and strict routing.

The path is normalized exactly the way the router normalizes an incoming
request before matching, so the answer agrees with what the app would actually
do. In particular, with the default StrictRouting: false a trailing slash on
the path is ignored, so RoutePatternMatch("/a/", "/a") reports true. Set
StrictRouting: true if you need the two forms to be distinguished.

go title="signature"
func RoutePatternMatch(path, pattern string, cfg ...Config) bool
go title="example"
fiber.RoutePatternMatch("/user/john", "/user/:name") // true

fiber.RoutePatternMatch(
    "/User/john",
    "/user/:name",
    fiber.Config{CaseSensitive: true},
) // false

2. Official Technical Reference & Guides (gofiber/docs)

File: README.md

Website

This website is built using Docusaurus 3, a modern static website generator.

Prerequisites

  • Node.js >= 20
  • npm >= 10

Installation

text
$ npm ci

Local Development

text
$ npm run start

This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.

Build

text
$ npm run build

This command generates static content into the build directory and can be served using any static contents hosting service.

Build only docs site:

text
$ npm run build:docs

Build only homepage:

text
$ npm run build:home

Run setup checks (TypeScript + both build targets):

text
$ npm run check

Deployment

Using SSH:

text
$ USE_SSH=true npm run deploy

Not using SSH:

text
$ GIT_USER=<Your GitHub username> npm run deploy

If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the gh-pages branch.


File: contrib_versioned_docs/version-websocket_v1.x.x/paseto/README.md


id: paseto

Paseto

PASETO returns a Web Token (PASETO) auth middleware.

  • For valid token, it sets the payload data in Ctx.Locals and calls next handler.
  • For invalid token, it returns "401 - Unauthorized" error.
  • For missing token, it returns "400 - BadRequest" error.

Note: Requires Go 1.18 and above

Install

This middleware supports Fiber v2.

text
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/paseto
go get -u github.com/o1egl/paseto

Signature

go
pasetoware.New(config ...pasetoware.Config) func(*fiber.Ctx) error

Config

Property Type Description Default
Next func(*Ctx) bool Defines a function to skip middleware nil
SuccessHandler func(*fiber.Ctx) error SuccessHandler defines a function which is executed for a valid token. c.Next()
ErrorHandler func(*fiber.Ctx, error) error ErrorHandler defines a function which is executed for an invalid token. 401 Invalid or expired PASETO
Validate PayloadValidator Defines a function to validate if payload is valid. Optional. In case payload used is created using CreateToken function. If token is created using another function, this function must be provided. nil
SymmetricKey []byte Secret key to encrypt token. If present the middleware will generate local tokens. nil
PrivateKey ed25519.PrivateKey Secret key to sign the tokens. If present (along with its PublicKey) the middleware will generate public tokens. nil
PublicKey crypto.PublicKey Public key to verify the tokens. If present (along with PrivateKey) the middleware will generate public tokens. nil
ContextKey string Context key to store user information from the token into context. "auth-token"
TokenLookup [2]string TokenLookup is a string slice with size 2, that is used to extract token from the request ["header","Authorization"]

Instructions

When using this middleware, and creating a token for authentication, you can use the function pasetoware.CreateToken,
that will create a token, encrypt or sign it and returns the PASETO token.

Passing a SymmetricKey in the Config results in a local (encrypted) token, while passing a PublicKey
and PrivateKey results in a public (signed) token.

In case you want to use your own data structure, is needed to provide the Validate function in paseware.Config, that
will return the data stored in the token, and a error.

Examples

Below have a list of some examples that can help you start to use this middleware. In case of any additional example
that doesn't show here, please take a look at the test file.

SymmetricKey

go
package main

import (
	"time"

	"github.com/gofiber/fiber/v2"
	"github.com/o1egl/paseto"

	pasetoware "github.com/gofiber/contrib/paseto"
)

const secretSymmetricKey = "symmetric-secret-key (size = 32)"

func main() {

	app := fiber.New()

	// Login route
	app.Post("/login", login)

	// Unauthenticated route
	app.Get("/", accessible)

	// Paseto Middleware with local (encrypted) token
	apiGroup := app.Group("api", pasetoware.New(pasetoware.Config{
		SymmetricKey: []byte(secretSymmetricKey),
		TokenPrefix:  "Bearer",
	}))

	// Restricted Routes
	apiGroup.Get("/restricted", restricted)

	err := app.Listen(":8088")
	if err != nil {
		return
	}
}

func login(c *fiber.Ctx) error {
	user := c.FormValue("user")
	pass := c.FormValue("pass")

	// Throws Unauthorized error
	if user != "john" || pass != "doe" {
		return c.SendStatus(fiber.StatusUnauthorized)
	}

	// Create token and encrypt it
	encryptedToken, err := pasetoware.CreateToken([]byte(secretSymmetricKey), user, 12*time.Hour, pasetoware.PurposeLocal)
	if err != nil {
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	return c.JSON(fiber.Map{"token": encryptedToken})
}

func accessible(c *fiber.Ctx) error {
	return c.SendString("Accessible")
}

func restricted(c *fiber.Ctx) error {
	payload := c.Locals(pasetoware.DefaultContextKey).(string)
	return c.SendString("Welcome " + payload)
}

Test it

Login using username and password to retrieve a token.

text
curl --data "user=john&pass=doe" http://localhost:8088/login

Response

json
{
  "token": "v2.local.eY7o9YAJ7Uqyo0JdyfHXKVARj3HgBhqIHckPgNIJOU6u489CXYL6bpOXbEtTB_nNM7nTFpcRVi7YAtJToxbxkkraHmE39pqjnBgkca-URgE-jhZGuhGu7ablmK-8tVoe5iY8mQqWFuJHAznTASUHh4AG55AMUcIALi6pEG28lAgVfw2azvnvbg4JOVZnjutcOVswd-ErsAuGtuEZkTmX7BfaLaO9ZvEX9cHahYPajuRjwU2TQrcpqITg-eYMNA1NuO8OVdnGf0mkUk6ElJUTZqhx4CSSylNXr7IlOwzTbUotEDAQTcNP7IRZI3VfpnRgnmtnZ5s.bnVsbAY"
}

Request a restricted resource using the token in Authorization request header.

text
curl localhost:8088/api/restricted -H "Authorization: Bearer v2.local.eY7o9YAJ7Uqyo0JdyfHXKVARj3HgBhqIHckPgNIJOU6u489CXYL6bpOXbEtTB_nNM7nTFpcRVi7YAtJToxbxkkraHmE39pqjnBgkca-URgE-jhZGuhGu7ablmK-8tVoe5iY8mQqWFuJHAznTASUHh4AG55AMUcIALi6pEG28lAgVfw2azvnvbg4JOVZnjutcOVswd-ErsAuGtuEZkTmX7BfaLaO9ZvEX9cHahYPajuRjwU2TQrcpqITg-eYMNA1NuO8OVdnGf0mkUk6ElJUTZqhx4CSSylNXr7IlOwzTbUotEDAQTcNP7IRZI3VfpnRgnmtnZ5s.bnVsbA"

Response

text
Welcome john

SymmetricKey + Custom Validator callback

go
package main

import (
	"encoding/json"
	"time"

	"github.com/o1egl/paseto"

	pasetoware "github.com/gofiber/contrib/paseto"
)

const secretSymmetricKey = "symmetric-secret-key (size = 32)"

type customPayloadStruct struct {
	Name      string    `json:"name"`
	ExpiresAt time.Time `json:"expiresAt"`
}

func main() {

	app := fiber.New()

	// Login route
	app.Post("/login", login)

	// Unauthenticated route
	app.Get("/", accessible)

	// Paseto Middleware with local (encrypted) token
	apiGroup := app.Group("api", pasetoware.New(pasetoware.Config{
		SymmetricKey: []byte(secretSymmetricKey),
		TokenPrefix:  "Bearer",
		Validate: func(decrypted []byte) (any, error) {
			var payload customPayloadStruct
			err := json.Unmarshal(decrypted, &payload)
			return payload, err
		},
	}))

	// Restricted Routes
	apiGroup.Get("/restricted", restricted)

	err := app.Listen(":8088")
	if err != nil {
		return
	}
}

func login(c *fiber.Ctx) error {
	user := c.FormValue("user")
	pass := c.FormValue("pass")

	// Throws Unauthorized error
	if user != "john" || pass != "doe" {
		return c.SendStatus(fiber.StatusUnauthorized)
	}

	// Create the payload
	payload := customPayloadStruct{
		Name:      "John Doe",
		ExpiresAt: time.Now().Add(12 * time.Hour),
	}

	// Create token and encrypt it
	encryptedToken, err := paseto.NewV2().Encrypt([]byte(secretSymmetricKey), payload, nil)
	if err != nil {
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	return c.JSON(fiber.Map{"token": encryptedToken})
}

func accessible(c *fiber.Ctx) error {
	return c.SendString("Accessible")
}

func restricted(c *fiber.Ctx) error {
	payload := c.Locals(pasetoware.DefaultContextKey).(customPayloadStruct)
	return c.SendString("Welcome " + payload.Name)
}

Test it

Login using username and password to retrieve a token.

text
curl --data "user=john&pass=doe" http://localhost:8088/login

Response

json
{
  "token": "v2.local.OSnDEMUndq8JpRdCD8yX-mr-Z0-Mi85Jw0ftxseiNLCbRc44Mxl5dnn-SV9Qew1n9Y44wXZwm_FG279cILJk7lYc_B_IoMCRBudJE7qMgctkD9UBM-ZRZgCX9ekJh3S1Oo6Erp7bO-omPra5.bnVsbA"
}

Request a restricted resource using the token in Authorization request header.

text
curl localhost:8088/api/restricted -H "Authorization: Bearer v2.local.OSnDEMUndq8JpRdCD8yX-mr-Z0-Mi85Jw0ftxseiNLCbRc44Mxl5dnn-SV9Qew1n9Y44wXZwm_FG279cILJk7lYc_B_IoMCRBudJE7qMgctkD9UBM-ZRZgCX9ekJh3S1Oo6Erp7bO-omPra5.bnVsbA"

Response

text
Welcome John Doe

PublicPrivate Key

go
package main

import (
	"crypto/ed25519"
	"encoding/hex"
	"time"

	"github.com/gofiber/fiber/v2"

	pasetoware "github.com/gofiber/contrib/paseto"
)

const privateKeySeed = "e9c67fe2433aa4110caf029eba70df2c822cad226b6300ead3dcae443ac3810f"

var seed, _ = hex.DecodeString(privateKeySeed)
var privateKey = ed25519.NewKeyFromSeed(seed)

type customPayloadStruct struct {
	Name      string    `json:"name"`
	ExpiresAt time.Time `json:"expiresAt"`
}

func main() {

	app := fiber.New()

	// Login route
	app.Post("/login", login)

	// Unauthenticated route
	app.Get("/", accessible)

	// Paseto Middleware with local (encrypted) token
	apiGroup := app.Group("api", pasetoware.New(pasetoware.Config{
		TokenPrefix: "Bearer",
		PrivateKey:  privateKey,
		PublicKey:   privateKey.Public(),
	}))

	// Restricted Routes
	apiGroup.Get("/restricted", restricted)

	err := app.Listen(":8088")
	if err != nil {
		return
	}
}

func login(c *fiber.Ctx) error {
	user := c.FormValue("user")
	pass := c.FormValue("pass")

	// Throws Unauthorized error
	if user != "john" || pass != "doe" {
		return c.SendStatus(fiber.StatusUnauthorized)
	}

	// Create token and encrypt it
	encryptedToken, err := pasetoware.CreateToken(privateKey, user, 12*time.Hour, pasetoware.PurposePublic)
	if err != nil {
		return c.SendStatus(fiber.StatusInternalServerError)
	}

	return c.JSON(fiber.Map{"token": encryptedToken})
}

func accessible(c *fiber.Ctx) error {
	return c.SendString("Accessible")
}

func restricted(c *fiber.Ctx) error {
	payload := c.Locals(pasetoware.DefaultContextKey).(string)
	return c.SendString("Welcome " + payload)
}

Test it

Login using username and password to retrieve a token.

text
curl --data "user=john&pass=doe" http://localhost:8088/login

Response

json
{
  "token": "v2.public.eyJhdWQiOiJnb2ZpYmVyLmdvcGhlcnMiLCJkYXRhIjoiam9obiIsImV4cCI6IjIwMjMtMDctMTNUMDg6NDk6MzctMDM6MDAiLCJpYXQiOiIyMDIzLTA3LTEyVDIwOjQ5OjM3LTAzOjAwIiwianRpIjoiMjIzYjM0MjQtNWNkZS00NDFhLWJiZWEtZjBjYWFhYTdiYWFlIiwibmJmIjoiMjAyMy0wNy0xMlQyMDo0OTozNy0wMzowMCIsInN1YiI6InVzZXItdG9rZW4ifWiqK_yg0eJbIs2hnup4NuBYg7v4lxh33zEhEljsH7QUaZXAdtbCPK7cN-NSfSxrw68owwgo-dOlPrD7lc5M_AU.bnVsbA"
}

Request a restricted resource using the token in Authorization request header.

text
curl localhost:8088/api/restricted -H "Authorization: Bearer v2.public.eyJhdWQiOiJnb2ZpYmVyLmdvcGhlcnMiLCJkYXRhIjoiam9obiIsImV4cCI6IjIwMjMtMDctMTNUMDg6NDk6MzctMDM6MDAiLCJpYXQiOiIyMDIzLTA3LTEyVDIwOjQ5OjM3LTAzOjAwIiwianRpIjoiMjIzYjM0MjQtNWNkZS00NDFhLWJiZWEtZjBjYWFhYTdiYWFlIiwibmJmIjoiMjAyMy0wNy0xMlQyMDo0OTozNy0wMzowMCIsInN1YiI6InVzZXItdG9rZW4ifWiqK_yg0eJbIs2hnup4NuBYg7v4lxh33zEhEljsH7QUaZXAdtbCPK7cN-NSfSxrw68owwgo-dOlPrD7lc5M_AU.bnVsbA"

Response

text
Welcome John Doe

File: contrib_versioned_docs/version-websocket_v1.x.x/otelfiber/example/README.md


id: otelfiber-example

Example

An HTTP server using gofiber fiber and instrumentation. The server has a
/users/:id endpoint. The server generates span information to
stdout.

These instructions expect you have
docker-compose installed.

Bring up the fiber-server and fiber-client services to run the
example:

sh
docker-compose up --detach fiber-server fiber-client

The fiber-client service sends just one HTTP request to fiber-server
and then exits. View the span generated by fiber-server in the logs:

sh
docker-compose logs fiber-server

Shut down the services when you are finished with the example:

sh
docker-compose down

File: contrib_versioned_docs/version-websocket_v1.x.x/otelfiber/README.md


id: otelfiber

Otelfiber

OpenTelemetry support for Fiber.

Can be found on OpenTelemetry Registry.

Note: Requires Go 1.19 and above

Install

This middleware supports Fiber v2.

text
go get -u github.com/gofiber/contrib/otelfiber/v2

Signature

go
otelfiber.Middleware(opts ...otelfiber.Option) fiber.Handler

Config

You can configure the middleware using functional parameters

Function Argument Type Description Default
WithNext func(*fiber.Ctx) bool Define a function to skip this middleware when returned true . nil
WithTracerProvider oteltrace.TracerProvider Specifies a tracer provider to use for creating a tracer. nil - the global tracer provider is used
WithMeterProvider otelmetric.MeterProvider Specifies a meter provider to use for reporting. nil - the global meter provider is used
WithPort int Specifies the value to use when setting the net.host.port attribute on metrics/spans. Defaults to (80 for http, 443 for https)
WithPropagators propagation.TextMapPropagator Specifies propagators to use for extracting information from the HTTP requests. If none are specified, global ones will be used
WithServerName string Specifies the value to use when setting the http.server_name attribute on metrics/spans. -
WithSpanNameFormatter func(*fiber.Ctx) string Takes a function that will be called on every request and the returned string will become the span Name. Default formatter returns the route pathRaw
WithCustomAttributes func(*fiber.Ctx) []attribute.KeyValue Define a function to add custom attributes to the span. nil
WithCustomMetricAttributes func(*fiber.Ctx) []attribute.KeyValue Define a function to add custom attributes to the metrics. nil
WithCollectClientIP bool Specifies whether to collect the client's IP address from the request. true

Usage

Please refer to example

Example

text
/* Detailed source-code truncated for AI context efficiency. */

File: contrib_versioned_docs/version-websocket_v1.x.x/opafiber/README.md


id: opafiber

Opafiber

Open Policy Agent support for Fiber.

Note: Requires Go 1.19 and above

Install

text
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/opafiber/v2

Signature

go
opafiber.New(config opafiber.Config) fiber.Handler

Config

Property Type Description Default
RegoQuery string Required - Rego query -
RegoPolicy io.Reader Required - Rego policy -
IncludeQueryString bool Include query string as input to rego policy false
DeniedStatusCode int Http status code to return when policy denies request 400
DeniedResponseMessage string Http response body text to return when policy denies request ""
IncludeHeaders []string Include headers as input to rego policy -
InputCreationMethod InputCreationFunc Use your own function to provide input for OPA func defaultInput(ctx *fiber.Ctx) (map[string]interface{}, error)

Types

go
type InputCreationFunc func(c *fiber.Ctx) (map[string]interface{}, error)

Usage

OPA Fiber middleware sends the following example data to the policy engine as input:

json
{
  "method": "GET",
  "path": "/somePath",
  "query": {
    "name": ["John Doe"]
  },
  "headers": {
    "Accept": "application/json",
    "Content-Type": "application/json"
  }
}
go
package main

import (
	"github.com/gofiber/fiber/v2"
	"github.com/gofiber/contrib/opafiber/v2"
)

func main() {
	app := fiber.New()
	module := `
package example.authz

default allow := false

allow {
	input.method == "GET"
}
`

	cfg := opafiber.Config{
		RegoQuery:             "data.example.authz.allow",
		RegoPolicy:            bytes.NewBufferString(module),
		IncludeQueryString:    true,
		DeniedStatusCode:      fiber.StatusForbidden,
		DeniedResponseMessage: "status forbidden",
		IncludeHeaders:        []string{"Authorization"},
		InputCreationMethod:   func (ctx *fiber.Ctx) (map[string]interface{}, error) {
            return map[string]interface{}{
                "method": ctx.Method(),
                "path": ctx.Path(),
            }, nil
        },
	}
	app.Use(opafiber.New(cfg))

	app.Get("/", func(ctx *fiber.Ctx) error {
		return ctx.SendStatus(200)
	})

	app.Listen(":8080")
}

File: contrib_versioned_docs/version-websocket_v1.x.x/monitor/README.md


id: monitor

Monitor

Monitor middleware for Fiber that reports server metrics, inspired by express-status-monitor

Install

This middleware supports Fiber v3.

text
go get -u github.com/gofiber/fiber/v3
go get -u github.com/gofiber/contrib/monitor

Signature

go
monitor.New(config ...monitor.Config) fiber.Handler

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 montioring API. false
Next func(c *fiber.Ctx) bool Define a function to add custom fields. nil
CustomHead string Custom HTML code to Head Section(Before End). empty
FontURL string FontURL for specilt font resource path or URL. also you can use relative path. https://fonts.googleapis.com/css2?family=Roboto:wght@400;900&display=swap
ChartJsURL string ChartJsURL for specilt chartjs library, path or URL, also you can use relative path. https://cdn.jsdelivr.net/npm/[email protected]/dist/Chart.bundle.min.js

Example

go
package main

import (
    "log"

    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/contrib/monitor"
)

func main() {
    app := fiber.New()

    // 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"}))

    log.Fatal(app.Listen(":3000"))
}

Default Config

go
var ConfigDefault = Config{
	Title:      defaultTitle,
	Refresh:    defaultRefresh,
	FontURL:    defaultFontURL,
	ChartJsURL: defaultChartJSURL,
	CustomHead: defaultCustomHead,
	APIOnly:    false,
	Next:       nil,
}

File: contrib_versioned_docs/version-websocket_v1.x.x/loadshed/README.md


id: loadshed

LoadShed

The LoadShed middleware for Fiber is designed to help manage server load by shedding requests based on certain load criteria.

Note: Requires Go 1.19 and above

Install

This middleware supports Fiber v2

text
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/loadshed

Signatures

go
loadshed.New(config ...loadshed.Config) fiber.Handler

Examples

To use the LoadShed middleware in your Fiber application, import it and apply it to your Fiber app. Here's an example:

go
package main

import (
  "github.com/gofiber/fiber/v2"
  loadshed "github.com/gofiber/contrib/loadshed"
)

func main() {
  app := fiber.New()

  // Configure and use LoadShed middleware
  app.Use(loadshed.New(loadshed.Config{
    Criteria: &loadshed.CPULoadCriteria{
      LowerThreshold: 0.75, // Set your own lower threshold
      UpperThreshold: 0.90, // Set your own upper threshold
      Interval:       10 * time.Second,
      Getter:         &loadshed.DefaultCPUPercentGetter{},
    },
  }))

  app.Get("/", func(c *fiber.Ctx) error {
    return c.SendString("Welcome!")
  })

  app.Listen(":3000")
}

Config

The LoadShed middleware in Fiber offers various configuration options to tailor the load shedding behavior according to the needs of your application.

Property Type Description Default
Next func(*fiber.Ctx) bool Function to skip this middleware when returned true. nil
Criteria LoadCriteria Interface for defining load shedding criteria. &CPULoadCriteria{...}

LoadCriteria

LoadCriteria is an interface in the LoadShed middleware that defines the criteria for determining when to shed load in the system. Different implementations of this interface can use various metrics and algorithms to decide when and how to shed incoming requests to maintain system performance.

CPULoadCriteria

CPULoadCriteria is an implementation of the LoadCriteria interface, using CPU load as the metric for determining whether to shed requests.

Properties

Property Type Description
LowerThreshold float64 The lower CPU usage threshold as a fraction (0.0 to 1.0). Requests are considered for shedding when CPU usage exceeds this threshold.
UpperThreshold float64 The upper CPU usage threshold as a fraction (0.0 to 1.0). All requests are shed when CPU usage exceeds this threshold.
Interval time.Duration The time interval over which the CPU usage is averaged for decision making.
Getter CPUPercentGetter Interface to retrieve CPU usage percentages.

How It Works

CPULoadCriteria determines the load on the system based on CPU usage and decides whether to shed incoming requests. It operates on the following principles:

  • CPU Usage Measurement: It measures the CPU usage over a specified interval.
  • Thresholds: Utilizes LowerThreshold and UpperThreshold values to decide when to start shedding requests.
  • Proportional Rejection Probability:
    • Below LowerThreshold: No requests are rejected, as the system is considered under acceptable load.
    • Between LowerThreshold and UpperThreshold: The probability of rejecting a request increases as the CPU usage approaches the UpperThreshold. This is calculated using the formula:
      plaintext
      rejectionProbability := (cpuUsage - LowerThreshold*100) / (UpperThreshold - LowerThreshold)
    • Above UpperThreshold: All requests are rejected to prevent system overload.

This mechanism ensures that the system can adaptively manage its load, maintaining stability and performance under varying traffic conditions.

Default Config

This is the default configuration for LoadCriteria in the LoadShed middleware.

go
var ConfigDefault = Config{
  Next: nil,
  Criteria: &CPULoadCriteria{
    LowerThreshold: 0.90,  // 90% CPU usage as the start point for considering shedding
    UpperThreshold: 0.95,  // 95% CPU usage as the point where all requests are shed
    Interval:       10 * time.Second,  // CPU usage is averaged over 10 seconds
    Getter:         &DefaultCPUPercentGetter{},  // Default method for getting CPU usage
  },
}

File: contrib_versioned_docs/version-websocket_v1.x.x/jwt/README.md


id: jwt

JWT

JWT returns a JSON Web Token (JWT) auth middleware.
For valid token, it sets the user in Ctx.Locals and calls next handler.
For invalid token, it returns "401 - Unauthorized" error.
For missing token, it returns "400 - Bad Request" error.

Special thanks and credits to Echo

Note: Requires Go 1.19 and above

Install

This middleware supports Fiber v1 & v2, install accordingly.

bash
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/jwt
go get -u github.com/golang-jwt/jwt/v5

Signature

go
jwtware.New(config ...jwtware.Config) func(*fiber.Ctx) error

Config

Property Type Description Default
Filter func(*fiber.Ctx) bool Function to skip middleware execution for specific requests. Optional. nil
SuccessHandler fiber.Handler Handler executed when a token is successfully validated. Optional. nil
ErrorHandler fiber.ErrorHandler Handler executed when token validation fails. Allows customization of JWT error responses. Optional. 401 Invalid or expired JWT
SigningKey SigningKey Primary key used to validate tokens. Used as a fallback if SigningKeys is empty. At least one of KeyFunc, JWKSetURLs, SigningKeys, or SigningKey is required. nil
SigningKeys map[string]SigningKey Map of keys used to validate tokens with the "kid" field. At least one of KeyFunc, JWKSetURLs, SigningKeys, or SigningKey is required. nil
ContextKey string Key used to store user information in the context. Optional. "user"
Claims jwt.Claims Defines the structure of token claims. Extendable for custom claims data. Optional. jwt.MapClaims{}
TokenLookup string Specifies how to extract the token from the request. Format: ":<name>" (e.g., "header:Authorization", "query:token", "param:token", "cookie:token"). Optional. "header:Authorization"
TokenProcessorFunc func(token string) (string, error) Processes the token extracted using TokenLookup. Optional. nil
AuthScheme string Scheme used in the Authorization header. Only used with the default TokenLookup. Optional. "Bearer"
KeyFunc func() jwt.Keyfunc Provides the public key for JWT verification, handling algorithm verification and key selection. At least one of KeyFunc, JWKSetURLs, SigningKeys, or SigningKey is required. jwtKeyFunc
JWKSetURLs []string List of URLs containing JSON Web Key Sets (JWKS) for signature verification. HTTPS is recommended. The "kid" field is mandatory in both the JWT header and the JWKS. Default behavior includes hourly refresh, auto-refresh on new "kid", rate limiting, and timeouts. nil

HS256 Example

go
package main

import (
 "time"

 "github.com/gofiber/fiber/v2"

 jwtware "github.com/gofiber/contrib/jwt"
 "github.com/golang-jwt/jwt/v5"
)

func main() {
 app := fiber.New()

 // Login route
 app.Post("/login", login)

 // Unauthenticated route
 app.Get("/", accessible)

 // JWT Middleware
 app.Use(jwtware.New(jwtware.Config{
  SigningKey: jwtware.SigningKey{Key: []byte("secret")},
 }))

 // Restricted Routes
 app.Get("/restricted", restricted)

 app.Listen(":3000")
}

func login(c *fiber.Ctx) error {
 user := c.FormValue("user")
 pass := c.FormValue("pass")

 // Throws Unauthorized error
 if user != "john" || pass != "doe" {
  return c.SendStatus(fiber.StatusUnauthorized)
 }

 // Create the Claims
 claims := jwt.MapClaims{
  "name":  "John Doe",
  "admin": true,
  "exp":   time.Now().Add(time.Hour * 72).Unix(),
 }

 // Create token
 token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)

 // Generate encoded token and send it as response.
 t, err := token.SignedString([]byte("secret"))
 if err != nil {
  return c.SendStatus(fiber.StatusInternalServerError)
 }

 return c.JSON(fiber.Map{"token": t})
}

func accessible(c *fiber.Ctx) error {
 return c.SendString("Accessible")
}

func restricted(c *fiber.Ctx) error {
 user := c.Locals("user").(*jwt.Token)
 claims := user.Claims.(jwt.MapClaims)
 name := claims["name"].(string)
 return c.SendString("Welcome " + name)
}

HS256 Test

Login using username and password to retrieve a token.

bash
curl --data "user=john&pass=doe" http://localhost:3000/login

Response

json
{
  "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"
}

Request a restricted resource using the token in Authorization request header.

bash
curl localhost:3000/restricted -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE0NjE5NTcxMzZ9.RB3arc4-OyzASAaUhC2W3ReWaXAt_z2Fd3BN4aWTgEY"

Response

text
Welcome John Doe

RS256 Example

text
/* Detailed source-code truncated for AI context efficiency. */

RS256 Test

The RS256 is actually identical to the HS256 test above.

JWK Set Test

The tests are identical to basic JWT tests above, with exception that JWKSetURLs to valid public keys collection in JSON Web Key (JWK) Set format should be supplied. See RFC 7517.

Custom KeyFunc example

KeyFunc defines a user-defined function that supplies the public key for a token validation.
The function shall take care of verifying the signing algorithm and selecting the proper key.
A user-defined KeyFunc can be useful if tokens are issued by an external party.

When a user-defined KeyFunc is provided, SigningKey, SigningKeys, and SigningMethod are ignored.
This is one of the three options to provide a token validation key.
The order of precedence is a user-defined KeyFunc, SigningKeys and SigningKey.
Required if neither SigningKeys nor SigningKey is provided.
Default to an internal implementation verifying the signing algorithm and selecting the proper key.

go
package main

import (
 "fmt"
  "github.com/gofiber/fiber/v2"

  jwtware "github.com/gofiber/contrib/jwt"
  "github.com/golang-jwt/jwt/v5"
)

func main() {
 app := fiber.New()

 app.Use(jwtware.New(jwtware.Config{
  KeyFunc: customKeyFunc(),
 }))

 app.Get("/ok", func(c *fiber.Ctx) error {
  return c.SendString("OK")
 })
}

func customKeyFunc() jwt.Keyfunc {
 return func(t *jwt.Token) (interface{}, error) {
  // Always check the signing method
  if t.Method.Alg() != jwtware.HS256 {
   return nil, fmt.Errorf("Unexpected jwt signing method=%v", t.Header["alg"])
  }

  // TODO custom implementation of loading signing key like from a database
    signingKey := "secret"

  return []byte(signingKey), nil
 }
}

File: contrib_versioned_docs/version-websocket_v1.x.x/hcaptcha/README.md


id: hcaptcha

HCaptcha

A simple HCaptcha middleware to prevent bot attacks.

:::note

Requires Go 1.21 and above

:::

Install

:::caution

This middleware only supports Fiber v3.

:::

shell
go get -u github.com/gofiber/fiber/v3
go get -u github.com/gofiber/contrib/hcaptcha

Signature

go
hcaptcha.New(config hcaptcha.Config) fiber.Handler

Config

Property Type Description Default
SecretKey string The secret key you obtained from the HCaptcha admin panel. This field must not be empty. ""
ResponseKeyFunc func(fiber.Ctx) (string, error) ResponseKeyFunc should return the token that captcha provides upon successful solving. By default, it gets the token from the body by parsing a JSON request and returns the hcaptcha_token field. hcaptcha.DefaultResponseKeyFunc
SiteVerifyURL string This property specifies the API resource used for token authentication. https://api.hcaptcha.com/siteverify

Example

go
package main

import (
    "github.com/gofiber/contrib/hcaptcha"
    "github.com/gofiber/fiber/v3"
    "log"
)

const (
    TestSecretKey = "0x0000000000000000000000000000000000000000"
    TestSiteKey   = "20000000-ffff-ffff-ffff-000000000002"
)

func main() {
    app := fiber.New()
    captcha := hcaptcha.New(hcaptcha.Config{
        // Must set the secret key
        SecretKey: TestSecretKey,
    })
	
    app.Get("/api/", func(c fiber.Ctx) error {
        return c.JSON(fiber.Map{
            "hcaptcha_site_key": TestSiteKey,
        })
    })
	
    app.Post("/api/robots-excluded", func(c fiber.Ctx) error {
        return c.SendString("You are not a robot")
    }, captcha)
	
    log.Fatal(app.Listen(":3000"))
}

File: contrib_versioned_docs/version-websocket_v1.x.x/fiberzerolog/README.md


id: fiberzerolog

Fiberzerolog

Zerolog logging support for Fiber.

Note: Requires Go 1.18 and above

Install

This middleware supports Fiber v2.

sh
go get -u github.com/gofiber/fiber/v2
go get -u github.com/gofiber/contrib/fiberzerolog
go get -u github.com/rs/zerolog/log

Signature

go
fiberzerolog.New(config ...fiberzerolog.Config) fiber.Handler

Config

Property Type Description Default
Next func(*Ctx) bool Define a function to skip this middleware when returned true nil
Logger *zerolog.Logger Add custom zerolog logger. zerolog.New(os.Stderr).With().Timestamp().Logger()
GetLogger func(*fiber.Ctx) zerolog.Logger Get custom zerolog logger, if it's defined the returned logger will replace the Logger value. nil
Fields []string Add fields what you want see. []string{"latency", "status", "method", "url", "error"}
WrapHeaders bool Wrap headers to dictionary.If false: {"method":"POST", "header-key":"header value"}If true: {"method":"POST", "reqHeaders": {"header-key":"header value"}} false
FieldsSnakeCase bool Use snake case for fields: FieldResBody, FieldQueryParams, FieldBytesReceived, FieldBytesSent, FieldRequestId, FieldReqHeaders, FieldResHeaders.If false: {"method":"POST", "resBody":"v", "queryParams":"v"}If true: {"method":"POST", "res_body":"v", "query_params":"v"} false
Messages []string Custom response messages. []string{"Server error", "Client error", "Success"}
Levels []zerolog.Level Custom response levels. []zerolog.Level{zerolog.ErrorLevel, zerolog.WarnLevel, zerolog.InfoLevel}
SkipURIs []string Skip logging these URI. []string{}
GetResBody func(c *fiber.Ctx) []byte Define a function to get response body when return non-nil.eg: When use compress middleware, resBody is unreadable. you can set GetResBody func to get readable resBody. nil

Example

go
package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/contrib/fiberzerolog"
    "github.com/rs/zerolog"
)

func main() {
    app := fiber.New()
    logger := zerolog.New(os.Stderr).With().Timestamp().Logger()

    app.Use(fiberzerolog.New(fiberzerolog.Config{
        Logger: &logger,
    }))

    app.Get("/", func (c *fiber.Ctx) error {
        return c.SendString("Hello, World!")
    })

    if err := app.Listen(":3000"); err != nil {
        logger.Fatal().Err(err).Msg("Fiber app error")
    }
}