fiber/docs/middleware/idempotency.md
RW ab7f949382
📒 docs: Idempotency add more detailed description for next method (#3443)
* add more detailed description for next method
2025-05-12 14:59:42 +02:00

4.8 KiB

id
id
idempotency

Idempotency

Idempotency middleware for Fiber allows for fault-tolerant APIs where duplicate requests—for example due to networking issues on the client-side — do not erroneously cause the same action to be performed multiple times on the server-side.

Refer to IETF RFC 7231 §4.2.2 for definitions of safe and idempotent HTTP methods.

HTTP Method Categories

  • Safe Methods (do not modify server state): GET, HEAD, OPTIONS, TRACE.
  • Idempotent Methods (multiple identical requests have the same effect as a single one): all safe methods plus PUT and DELETE.

According to the RFC, safe methods are guaranteed not to change server state, while idempotent methods may change state but make identical requests safe to repeat.

Signatures

func New(config ...Config) fiber.Handler
func IsFromCache(c fiber.Ctx) bool
func WasPutToCache(c fiber.Ctx) bool

Examples

Import the middleware package that is part of the Fiber web framework

import (
    "github.com/gofiber/fiber/v3"
    "github.com/gofiber/fiber/v3/middleware/idempotency"
)

After you initiate your Fiber app, you can configure the middleware:

Default Config (Skip Safe Methods)

By default, the Next function skips middleware for safe methods only:

app.Use(idempotency.New())

Skip Idempotent Methods Instead

If you prefer to skip middleware on all idempotent methods (including PUT, DELETE), override Next:

app.Use(idempotency.New(idempotency.Config{
    Next: func(c fiber.Ctx) bool {
        // Skip middleware for idempotent methods (safe + PUT, DELETE)
        return fiber.IsMethodIdempotent(c.Method())
    },
}))

Custom Config

app.Use(idempotency.New(idempotency.Config{
    Lifetime: 42 * time.Minute,
    // ...
}))

Config

Property Type Description Default
Next func(fiber.Ctx) bool Function to skip this middleware when returning true. Choose between IsMethodSafe or IsMethodIdempotent based on RFC definitions. func(c fiber.Ctx) bool { return fiber.IsMethodSafe(c.Method()) }
Lifetime time.Duration Maximum lifetime of an idempotency key. 30 * time.Minute
KeyHeader string Header name containing the idempotency key. "X-Idempotency-Key"
KeyHeaderValidate func(string) error Function to validate idempotency header syntax (e.g., UUID). UUID length check (36 characters)
KeepResponseHeaders []string List of headers to preserve from original response. nil (keep all headers)
Lock Locker Locks an idempotency key to prevent race conditions. In-memory locker
Storage fiber.Storage Stores response data by idempotency key. In-memory storage

Default Config Values

var ConfigDefault = Config{
    Next: func(c fiber.Ctx) bool {
        // Skip middleware for safe methods per RFC 7231 §4.2.2
        return fiber.IsMethodSafe(c.Method())
    },

    Lifetime: 30 * time.Minute,

    KeyHeader: "X-Idempotency-Key",
    KeyHeaderValidate: func(k string) error {
        if l, wl := len(k), 36; l != wl { // UUID length is 36 chars
            return fmt.Errorf("%w: invalid length: %d != %d", ErrInvalidIdempotencyKey, l, wl)
        }

        return nil
    },

    KeepResponseHeaders: nil,

    Lock: nil, // Set in configDefault so we don't allocate data here.

    Storage: nil, // Set in configDefault so we don't allocate data here.
}