mirror of
https://github.com/dutchcoders/transfer.sh.git
synced 2024-12-04 18:00:19 +01:00
72 lines
2 KiB
Go
72 lines
2 KiB
Go
|
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))
|
||
|
}
|