Просмотр исходного кода

Support proxying images

This should make it faster because the actual favicons are now cached,
too.  Especially over HTTP/2 connections, this should improve the
response times quite a bit.
Lucas Stadler лет назад: 9
Родитель
Сommit
6a9c715e4a
1 измененных файлов с 54 добавлено и 0 удалено
  1. 54 0
      go/favicon/favicon.go

+ 54 - 0
go/favicon/favicon.go

4
	"errors"
4
	"errors"
5
	"flag"
5
	"flag"
6
	"fmt"
6
	"fmt"
7
	"io/ioutil"
7
	"net/http"
8
	"net/http"
8
	"net/url"
9
	"net/url"
9
	"os"
10
	"os"
21
var faviconCache *lru.Cache
22
var faviconCache *lru.Cache
22
var lock sync.RWMutex
23
var lock sync.RWMutex
23
24
25
var imageCache *lru.Cache
26
var imageLock sync.RWMutex
27
24
func main() {
28
func main() {
25
	flag.Parse()
29
	flag.Parse()
26
30
27
	faviconCache = lru.New(*cacheSize)
31
	faviconCache = lru.New(*cacheSize)
32
	imageCache = lru.New(*cacheSize)
28
33
29
	http.HandleFunc("/favicon", HandleGetFavicon)
34
	http.HandleFunc("/favicon", HandleGetFavicon)
35
	http.HandleFunc("/favicon_proxy", HandleProxy)
30
	if p := os.Getenv("PORT"); p != "" {
36
	if p := os.Getenv("PORT"); p != "" {
31
		flag.Set("p", p)
37
		flag.Set("p", p)
32
	}
38
	}
40
	}
46
	}
41
}
47
}
42
48
49
func HandleProxy(w http.ResponseWriter, r *http.Request) {
50
	url := r.URL.Query()["url"][0]
51
	favicon, err := GetFaviconCached(url)
52
	if err != nil {
53
		fmt.Printf("Error: '%s': %s\n", url, err)
54
		w.WriteHeader(http.StatusNotFound)
55
		w.Write([]byte(fmt.Sprint(err)))
56
		return
57
	}
58
59
	image, err := GetImageCached(favicon)
60
	if err != nil {
61
		fmt.Printf("Error: '%s': %s\n", url, err)
62
		w.WriteHeader(http.StatusNotFound)
63
		w.Write([]byte(fmt.Sprint(err)))
64
		return
65
	}
66
67
	w.Write(image)
68
}
69
70
func GetImageCached(u string) ([]byte, error) {
71
	imageLock.RLock()
72
	image, cached := imageCache.Get(u)
73
	imageLock.RUnlock()
74
75
	if cached {
76
		return image.([]byte), nil
77
	}
78
79
	resp, err := http.Get(u)
80
	if err != nil {
81
		return nil, err
82
	}
83
	defer resp.Body.Close()
84
85
	imageData, err := ioutil.ReadAll(resp.Body)
86
	if err != nil {
87
		return nil, err
88
	}
89
90
	imageLock.Lock()
91
	imageCache.Add(u, imageData)
92
	imageLock.Unlock()
93
	return imageData, nil
94
95
}
96
43
func HandleGetFavicon(w http.ResponseWriter, r *http.Request) {
97
func HandleGetFavicon(w http.ResponseWriter, r *http.Request) {
44
	url := r.URL.Query()["url"][0]
98
	url := r.URL.Query()["url"][0]
45
	favicon, err := GetFaviconCached(url)
99
	favicon, err := GetFaviconCached(url)