github.com/gofiber/fiber/v2@v2.47.0/middleware/favicon/favicon.go (about) 1 package favicon 2 3 import ( 4 "io" 5 "net/http" 6 "os" 7 "strconv" 8 9 "github.com/gofiber/fiber/v2" 10 ) 11 12 // Config defines the config for middleware. 13 type Config struct { 14 // Next defines a function to skip this middleware when returned true. 15 // 16 // Optional. Default: nil 17 Next func(c *fiber.Ctx) bool 18 19 // File holds the path to an actual favicon that will be cached 20 // 21 // Optional. Default: "" 22 File string `json:"file"` 23 24 // URL for favicon handler 25 // 26 // Optional. Default: "/favicon.ico" 27 URL string `json:"url"` 28 29 // FileSystem is an optional alternate filesystem to search for the favicon in. 30 // An example of this could be an embedded or network filesystem 31 // 32 // Optional. Default: nil 33 FileSystem http.FileSystem `json:"-"` 34 35 // CacheControl defines how the Cache-Control header in the response should be set 36 // 37 // Optional. Default: "public, max-age=31536000" 38 CacheControl string `json:"cache_control"` 39 } 40 41 // ConfigDefault is the default config 42 var ConfigDefault = Config{ 43 Next: nil, 44 File: "", 45 URL: fPath, 46 CacheControl: "public, max-age=31536000", 47 } 48 49 const ( 50 fPath = "/favicon.ico" 51 hType = "image/x-icon" 52 hAllow = "GET, HEAD, OPTIONS" 53 hZero = "0" 54 ) 55 56 // New creates a new middleware handler 57 func New(config ...Config) fiber.Handler { 58 // Set default config 59 cfg := ConfigDefault 60 61 // Override config if provided 62 if len(config) > 0 { 63 cfg = config[0] 64 65 // Set default values 66 if cfg.Next == nil { 67 cfg.Next = ConfigDefault.Next 68 } 69 if cfg.URL == "" { 70 cfg.URL = ConfigDefault.URL 71 } 72 if cfg.File == "" { 73 cfg.File = ConfigDefault.File 74 } 75 if cfg.CacheControl == "" { 76 cfg.CacheControl = ConfigDefault.CacheControl 77 } 78 } 79 80 // Load icon if provided 81 var ( 82 err error 83 icon []byte 84 iconLen string 85 ) 86 if cfg.File != "" { 87 // read from configured filesystem if present 88 if cfg.FileSystem != nil { 89 f, err := cfg.FileSystem.Open(cfg.File) 90 if err != nil { 91 panic(err) 92 } 93 if icon, err = io.ReadAll(f); err != nil { 94 panic(err) 95 } 96 } else if icon, err = os.ReadFile(cfg.File); err != nil { 97 panic(err) 98 } 99 100 iconLen = strconv.Itoa(len(icon)) 101 } 102 103 // Return new handler 104 return func(c *fiber.Ctx) error { 105 // Don't execute middleware if Next returns true 106 if cfg.Next != nil && cfg.Next(c) { 107 return c.Next() 108 } 109 110 // Only respond to favicon requests 111 if c.Path() != cfg.URL { 112 return c.Next() 113 } 114 115 // Only allow GET, HEAD and OPTIONS requests 116 if c.Method() != fiber.MethodGet && c.Method() != fiber.MethodHead { 117 if c.Method() != fiber.MethodOptions { 118 c.Status(fiber.StatusMethodNotAllowed) 119 } else { 120 c.Status(fiber.StatusOK) 121 } 122 c.Set(fiber.HeaderAllow, hAllow) 123 c.Set(fiber.HeaderContentLength, hZero) 124 return nil 125 } 126 127 // Serve cached favicon 128 if len(icon) > 0 { 129 c.Set(fiber.HeaderContentLength, iconLen) 130 c.Set(fiber.HeaderContentType, hType) 131 c.Set(fiber.HeaderCacheControl, cfg.CacheControl) 132 return c.Status(fiber.StatusOK).Send(icon) 133 } 134 135 return c.SendStatus(fiber.StatusNoContent) 136 } 137 }