github.com/gofiber/fiber/v2@v2.47.0/middleware/idempotency/config.go (about) 1 package idempotency 2 3 import ( 4 "errors" 5 "fmt" 6 "time" 7 8 "github.com/gofiber/fiber/v2" 9 "github.com/gofiber/fiber/v2/internal/storage/memory" 10 ) 11 12 var ErrInvalidIdempotencyKey = errors.New("invalid idempotency key") 13 14 // Config defines the config for middleware. 15 type Config struct { 16 // Next defines a function to skip this middleware when returned true. 17 // 18 // Optional. Default: a function which skips the middleware on safe HTTP request method. 19 Next func(c *fiber.Ctx) bool 20 21 // Lifetime is the maximum lifetime of an idempotency key. 22 // 23 // Optional. Default: 30 * time.Minute 24 Lifetime time.Duration 25 26 // KeyHeader is the name of the header that contains the idempotency key. 27 // 28 // Optional. Default: X-Idempotency-Key 29 KeyHeader string 30 // KeyHeaderValidate defines a function to validate the syntax of the idempotency header. 31 // 32 // Optional. Default: a function which ensures the header is 36 characters long (the size of an UUID). 33 KeyHeaderValidate func(string) error 34 35 // KeepResponseHeaders is a list of headers that should be kept from the original response. 36 // 37 // Optional. Default: nil (to keep all headers) 38 KeepResponseHeaders []string 39 40 // Lock locks an idempotency key. 41 // 42 // Optional. Default: an in-memory locker for this process only. 43 Lock Locker 44 45 // Storage stores response data by idempotency key. 46 // 47 // Optional. Default: an in-memory storage for this process only. 48 Storage fiber.Storage 49 } 50 51 // ConfigDefault is the default config 52 var ConfigDefault = Config{ 53 Next: func(c *fiber.Ctx) bool { 54 // Skip middleware if the request was done using a safe HTTP method 55 return fiber.IsMethodSafe(c.Method()) 56 }, 57 58 Lifetime: 30 * time.Minute, 59 60 KeyHeader: "X-Idempotency-Key", 61 KeyHeaderValidate: func(k string) error { 62 if l, wl := len(k), 36; l != wl { // UUID length is 36 chars 63 return fmt.Errorf("%w: invalid length: %d != %d", ErrInvalidIdempotencyKey, l, wl) 64 } 65 66 return nil 67 }, 68 69 KeepResponseHeaders: nil, 70 71 Lock: nil, // Set in configDefault so we don't allocate data here. 72 73 Storage: nil, // Set in configDefault so we don't allocate data here. 74 } 75 76 // Helper function to set default values 77 func configDefault(config ...Config) Config { 78 // Return default config if nothing provided 79 if len(config) < 1 { 80 return ConfigDefault 81 } 82 83 // Override default config 84 cfg := config[0] 85 86 // Set default values 87 88 if cfg.Next == nil { 89 cfg.Next = ConfigDefault.Next 90 } 91 92 if cfg.Lifetime.Nanoseconds() == 0 { 93 cfg.Lifetime = ConfigDefault.Lifetime 94 } 95 96 if cfg.KeyHeader == "" { 97 cfg.KeyHeader = ConfigDefault.KeyHeader 98 } 99 if cfg.KeyHeaderValidate == nil { 100 cfg.KeyHeaderValidate = ConfigDefault.KeyHeaderValidate 101 } 102 103 if cfg.KeepResponseHeaders != nil && len(cfg.KeepResponseHeaders) == 0 { 104 cfg.KeepResponseHeaders = ConfigDefault.KeepResponseHeaders 105 } 106 107 if cfg.Lock == nil { 108 cfg.Lock = NewMemoryLock() 109 } 110 111 if cfg.Storage == nil { 112 cfg.Storage = memory.New(memory.Config{ 113 GCInterval: cfg.Lifetime / 2, // Half the lifetime interval 114 }) 115 } 116 117 return cfg 118 }