瀏覽代碼

Send cache headers with the proxied images

Lucas Stadler 9 年之前
父節點
當前提交
81488c239e
共有 1 個文件被更改,包括 22 次插入6 次删除
  1. 22 6
      go/favicon/favicon.go

+ 22 - 6
go/favicon/favicon.go

@ -1,6 +1,7 @@
1 1
package main
2 2
3 3
import (
4
	"crypto/md5"
4 5
	"errors"
5 6
	"flag"
6 7
	"fmt"
@ -23,6 +24,7 @@ var faviconCache *lru.Cache
23 24
var lock sync.RWMutex
24 25
25 26
var imageCache *lru.Cache
27
var imageHashes *lru.Cache
26 28
var imageLock sync.RWMutex
27 29
28 30
func main() {
@ -30,6 +32,7 @@ func main() {
30 32
31 33
	faviconCache = lru.New(*cacheSize)
32 34
	imageCache = lru.New(*cacheSize)
35
	imageHashes = lru.New(*cacheSize)
33 36
34 37
	http.HandleFunc("/favicon", HandleGetFavicon)
35 38
	http.HandleFunc("/favicon_proxy", HandleProxy)
@ -47,6 +50,8 @@ func main() {
47 50
}
48 51
49 52
func HandleProxy(w http.ResponseWriter, r *http.Request) {
53
	w.Header().Set("Cache-Control", "max-age=2419200")
54
50 55
	url := r.URL.Query()["url"][0]
51 56
	favicon, err := GetFaviconCached(url)
52 57
	if err != nil {
@ -56,41 +61,52 @@ func HandleProxy(w http.ResponseWriter, r *http.Request) {
56 61
		return
57 62
	}
58 63
59
	image, err := GetImageCached(favicon)
64
	image, hash, err := GetImageCached(favicon)
60 65
	if err != nil {
61 66
		fmt.Printf("Error: '%s': %s\n", url, err)
62 67
		w.WriteHeader(http.StatusNotFound)
63 68
		w.Write([]byte(fmt.Sprint(err)))
64 69
		return
65 70
	}
71
	w.Header().Set("ETag", hash)
72
73
	ifNoneMatch := r.Header.Get("If-None-Match")
74
	if ifNoneMatch != "" && hash == ifNoneMatch {
75
		w.WriteHeader(http.StatusNotModified)
76
		return
77
	}
66 78
79
	w.Header().Set("Content-Length", fmt.Sprintf("%d", len(image)))
67 80
	w.Write(image)
68 81
}
69 82
70
func GetImageCached(u string) ([]byte, error) {
83
func GetImageCached(u string) ([]byte, string, error) {
71 84
	imageLock.RLock()
72 85
	image, cached := imageCache.Get(u)
86
	hash, _ := imageHashes.Get(u)
73 87
	imageLock.RUnlock()
74 88
75 89
	if cached {
76
		return image.([]byte), nil
90
		return image.([]byte), hash.(string), nil
77 91
	}
78 92
79 93
	resp, err := http.Get(u)
80 94
	if err != nil {
81
		return nil, err
95
		return nil, "", err
82 96
	}
83 97
	defer resp.Body.Close()
84 98
85 99
	imageData, err := ioutil.ReadAll(resp.Body)
86 100
	if err != nil {
87
		return nil, err
101
		return nil, "", err
88 102
	}
103
	imageHash := fmt.Sprintf("%x", md5.Sum(imageData))
89 104
90 105
	imageLock.Lock()
91 106
	imageCache.Add(u, imageData)
107
	imageHashes.Add(u, imageHash)
92 108
	imageLock.Unlock()
93
	return imageData, nil
109
	return imageData, imageHash, nil
94 110
95 111
}
96 112