|
- package handlers
-
- import (
- "crypto/md5"
- "io/ioutil"
- "net/http"
- "strconv"
- "time"
-
- "github.com/PuerkitoBio/ghost"
- )
-
- // FaviconHandlerFunc is the same as FaviconHandler, it is just a convenience
- // signature that accepts a func(http.ResponseWriter, *http.Request) instead of
- // a http.Handler interface. It saves the boilerplate http.HandlerFunc() cast.
- func FaviconHandlerFunc(h http.HandlerFunc, path string, maxAge time.Duration) http.HandlerFunc {
- return FaviconHandler(h, path, maxAge)
- }
-
- // Efficient favicon handler, mostly a port of node's Connect library implementation
- // of the favicon middleware.
- // https://github.com/senchalabs/connect
- func FaviconHandler(h http.Handler, path string, maxAge time.Duration) http.HandlerFunc {
- var buf []byte
- var hash string
-
- return func(w http.ResponseWriter, r *http.Request) {
- var err error
- if r.URL.Path == "/favicon.ico" {
- if buf == nil {
- // Read from file and cache
- ghost.LogFn("ghost.favicon : serving from %s", path)
- buf, err = ioutil.ReadFile(path)
- if err != nil {
- ghost.LogFn("ghost.favicon : error reading file : %s", err)
- http.NotFound(w, r)
- return
- }
- hash = hashContent(buf)
- }
- writeHeaders(w.Header(), buf, maxAge, hash)
- writeBody(w, r, buf)
- } else {
- h.ServeHTTP(w, r)
- }
- }
- }
-
- // Write the content of the favicon, or respond with a 404 not found
- // in case of error (hardly a critical error).
- func writeBody(w http.ResponseWriter, r *http.Request, buf []byte) {
- _, err := w.Write(buf)
- if err != nil {
- ghost.LogFn("ghost.favicon : error writing response : %s", err)
- http.NotFound(w, r)
- }
- }
-
- // Correctly set the http headers.
- func writeHeaders(hdr http.Header, buf []byte, maxAge time.Duration, hash string) {
- hdr.Set("Content-Type", "image/x-icon")
- hdr.Set("Content-Length", strconv.Itoa(len(buf)))
- hdr.Set("Etag", hash)
- hdr.Set("Cache-Control", "public, max-age="+strconv.Itoa(int(maxAge.Seconds())))
- }
-
- // Get the MD5 hash of the content.
- func hashContent(buf []byte) string {
- h := md5.New()
- return string(h.Sum(buf))
- }
|