-
Notifications
You must be signed in to change notification settings - Fork 0
/
favicon.go
65 lines (52 loc) · 1.43 KB
/
favicon.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package gpic
import (
"errors"
"fmt"
"net/http"
"net/url"
"time"
"slices"
)
var faviconFileTypes = []string{"svg", "png", "ico"}
var faviconContentTypes = []string{
"image/svg+xml",
"image/x-png",
"image/png",
"image/x-icon",
"image/vnd.microsoft.icon",
}
var ErrNotFound = errors.New("A favicon was not found.")
/*
* Finds and returns a URL to a favicon. The favicon is searched for on the
* hostname provided. Currently will return only the very first favicon found
* regardless of size, filetype, etc.
*
* For now this fuction only checks for favicons at the root of the website.
*/
func GetFavicon(URL *url.URL) (string, error) {
// check cache first
url, found := strCache.read("fav" + URL.String())
if found {
return url, nil
}
// Prep the URL. Drop any path from the URL as we're only concerned about
// hostnames
inputURL := fmt.Sprintf("%s://%s/favicon.", URL.Scheme, URL.Host)
client := &http.Client{
Timeout: time.Duration(time.Second * 10),
}
// try for each favicon filetype at the root of the hostname
for _, fileType := range faviconFileTypes {
resp, err := client.Get(inputURL + fileType)
if err != nil {
return "", err
}
defer resp.Body.Close()
if resp.StatusCode == 200 && slices.Contains(faviconContentTypes, resp.Header.Get("Content-Type")) {
// write to cache
strCache.write("fav"+URL.String(), inputURL+fileType)
return inputURL + fileType, nil
}
}
return "", ErrNotFound
}