mirror of
https://github.com/gofiber/fiber.git
synced 2025-02-22 15:03:57 +00:00
This change exists to support go 1.16 embedded filesystems and other network filesystems that can't simply be read as a file from a system path.
129 lines
2.8 KiB
Go
129 lines
2.8 KiB
Go
package favicon
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"net/http"
|
|
"strconv"
|
|
|
|
"github.com/gofiber/fiber/v2"
|
|
)
|
|
|
|
// Config defines the config for middleware.
|
|
type Config struct {
|
|
// Next defines a function to skip this middleware when returned true.
|
|
//
|
|
// Optional. Default: nil
|
|
Next func(c *fiber.Ctx) bool
|
|
|
|
// File holds the path to an actual favicon that will be cached
|
|
//
|
|
// Optional. Default: ""
|
|
File string `json:"file"`
|
|
|
|
// FileSystem is an optional alternate filesystem to search for the favicon in.
|
|
// An example of this could be an embedded or network filesystem
|
|
//
|
|
// Optional. Default: nil
|
|
FileSystem http.FileSystem `json:"-"`
|
|
|
|
// CacheControl defines how the Cache-Control header in the response should be set
|
|
//
|
|
// Optional. Default: "public, max-age=31536000"
|
|
CacheControl string `json:"cache_control"`
|
|
}
|
|
|
|
// ConfigDefault is the default config
|
|
var ConfigDefault = Config{
|
|
Next: nil,
|
|
File: "",
|
|
CacheControl: "public, max-age=31536000",
|
|
}
|
|
|
|
const (
|
|
hType = "image/x-icon"
|
|
hAllow = "GET, HEAD, OPTIONS"
|
|
hZero = "0"
|
|
)
|
|
|
|
// New creates a new middleware handler
|
|
func New(config ...Config) fiber.Handler {
|
|
// Set default config
|
|
cfg := ConfigDefault
|
|
|
|
// Override config if provided
|
|
if len(config) > 0 {
|
|
cfg = config[0]
|
|
|
|
// Set default values
|
|
if cfg.Next == nil {
|
|
cfg.Next = ConfigDefault.Next
|
|
}
|
|
if cfg.File == "" {
|
|
cfg.File = ConfigDefault.File
|
|
}
|
|
if cfg.CacheControl == "" {
|
|
cfg.CacheControl = ConfigDefault.CacheControl
|
|
}
|
|
}
|
|
|
|
// Load icon if provided
|
|
var (
|
|
err error
|
|
icon []byte
|
|
iconLen string
|
|
)
|
|
if cfg.File != "" {
|
|
// read from configured filesystem if present
|
|
if cfg.FileSystem != nil {
|
|
f, err := cfg.FileSystem.Open(cfg.File)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if icon, err = ioutil.ReadAll(f); err != nil {
|
|
panic(err)
|
|
}
|
|
} else {
|
|
if icon, err = ioutil.ReadFile(cfg.File); err != nil {
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
iconLen = strconv.Itoa(len(icon))
|
|
}
|
|
|
|
// Return new handler
|
|
return func(c *fiber.Ctx) error {
|
|
// Don't execute middleware if Next returns true
|
|
if cfg.Next != nil && cfg.Next(c) {
|
|
return c.Next()
|
|
}
|
|
|
|
// Only respond to favicon requests
|
|
if len(c.Path()) != 12 || c.Path() != "/favicon.ico" {
|
|
return c.Next()
|
|
}
|
|
|
|
// Only allow GET, HEAD and OPTIONS requests
|
|
if c.Method() != fiber.MethodGet && c.Method() != fiber.MethodHead {
|
|
if c.Method() != fiber.MethodOptions {
|
|
c.Status(fiber.StatusMethodNotAllowed)
|
|
} else {
|
|
c.Status(fiber.StatusOK)
|
|
}
|
|
c.Set(fiber.HeaderAllow, hAllow)
|
|
c.Set(fiber.HeaderContentLength, hZero)
|
|
return nil
|
|
}
|
|
|
|
// Serve cached favicon
|
|
if len(icon) > 0 {
|
|
c.Set(fiber.HeaderContentLength, iconLen)
|
|
c.Set(fiber.HeaderContentType, hType)
|
|
c.Set(fiber.HeaderCacheControl, cfg.CacheControl)
|
|
return c.Status(fiber.StatusOK).Send(icon)
|
|
}
|
|
|
|
return c.SendStatus(fiber.StatusNoContent)
|
|
}
|
|
}
|