a simple url shortener in Go (check it out at qurl.org)
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
|
|
package pages
import ( "bytes" "compress/gzip" "crypto/md5" "fmt" "net/http" "strings" )
type StaticContent struct { Type string Content []byte ETag string GZIPContent []byte GZIPETag string }
func (sc *StaticContent) Init() { // Populate ETag
sc.ETag = fmt.Sprintf("%x", md5.Sum(sc.Content))
// Set a default Content-Type, if needed
if sc.Type == "" { sc.Type = "application/octet-stream" }
var buf bytes.Buffer gz, _ := gzip.NewWriterLevel(&buf, gzip.BestCompression) defer gz.Close()
if _, err := gz.Write(sc.Content); err != nil { return }
if err := gz.Flush(); err != nil { return }
// Using gzip encoding adds a minimum of 24 characters to the HTTP
// header, so only accept gzip encoding if we save that much or more
if (buf.Len() + 24) < len(sc.Content) { sc.GZIPContent = buf.Bytes() sc.GZIPETag = fmt.Sprintf("%x", md5.Sum(sc.GZIPContent)) } }
func (sc *StaticContent) ServeHTTP(w http.ResponseWriter, r *http.Request) { gzok := strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") gzlen := len(sc.GZIPContent)
// Use the correct etag
var localETag string if gzok && gzlen > 0 { localETag = sc.GZIPETag } else { localETag = sc.ETag }
// Check the etag, maybe we don't need to send content
remoteETag := r.Header.Get("If-None-Match") if localETag == remoteETag { w.WriteHeader(http.StatusNotModified) return } w.Header().Set("ETag", localETag) w.Header().Set("Content-Type", sc.Type)
// Finally, write our content
if gzok && gzlen > 0 { w.Header().Set("Content-Encoding", "gzip") w.Header().Set("Content-Length", fmt.Sprintf("%d", gzlen)) w.Write(sc.GZIPContent) } else { w.Header().Set("Content-Length", fmt.Sprintf("%d", len(sc.Content))) w.Write(sc.Content) } }
|