reprogl

Форк
0
/
assets.go 
105 строк · 1.9 Кб
1
package views
2

3
import (
4
	"crypto/sha256"
5
	"encoding/base64"
6
	"fmt"
7
	"html/template"
8
	"os"
9
	"strconv"
10
	"strings"
11

12
	"xelbot.com/reprogl/container"
13
)
14

15
var fileHashes = make(map[string]string)
16

17
func cdnBase() string {
18
	return container.GetConfig().CDNBaseURL
19
}
20

21
func assetTag(file string) template.HTML {
22
	var (
23
		tmpl    string
24
		result  string
25
		subPath string
26
		ext     string
27
	)
28

29
	result, ok := fileHashes[file]
30
	if ok {
31
		return template.HTML(result)
32
	}
33

34
	if strings.HasSuffix(file, ".css") {
35
		tmpl = `<link rel="stylesheet" href="%s" integrity="%s" crossorigin="anonymous">`
36
		subPath = file[:len(file)-3]
37
		ext = ".css"
38
	} else if strings.HasSuffix(file, ".js") {
39
		tmpl = `<script src="%s" integrity="%s" crossorigin="anonymous"></script>`
40
		subPath = file[:len(file)-2]
41
		ext = ".js"
42
	} else {
43
		tmpl = `<unknown src="%s" integrity="%s"/>`
44
		subPath = file
45
		ext = ".?"
46
	}
47

48
	hash := subresourceIntegrity(file)
49
	timeBasedPart := timeBased(file)
50

51
	result = fmt.Sprintf(tmpl, cdnBase()+"/"+subPath+timeBasedPart+ext, hash)
52
	if !container.IsDevMode() {
53
		fileHashes[file] = result
54
	}
55

56
	return template.HTML(result)
57
}
58

59
func subresourceIntegrity(file string) string {
60
	var n int
61

62
	f, err := os.Open("./public/" + file)
63
	if err != nil {
64
		return ""
65
	}
66

67
	defer f.Close()
68

69
	hash := sha256.New()
70
	bytes := make([]byte, 1024)
71
	for {
72
		n, err = f.Read(bytes)
73
		if err != nil {
74
			break
75
		}
76

77
		hash.Write(bytes[:n])
78
	}
79

80
	return "sha256-" + base64.StdEncoding.EncodeToString(hash.Sum(nil))
81
}
82

83
func timeBased(file string) string {
84
	fileInfo, err := os.Stat("./public/" + file)
85
	if err != nil {
86
		return "v999"
87
	}
88

89
	modificatedAt := fileInfo.ModTime()
90

91
	return fmt.Sprintf(
92
		"v%d%s%s%s%s",
93
		modificatedAt.Year()%100,
94
		zeroPad(modificatedAt.YearDay(), 3),
95
		zeroPad(modificatedAt.Hour(), 2),
96
		zeroPad(modificatedAt.Minute(), 2),
97
		zeroPad(modificatedAt.Second(), 2),
98
	)
99
}
100

101
func zeroPad(i, width int) string {
102
	istring := strconv.Itoa(i)
103

104
	return strings.Repeat("0", width-len(istring)) + istring
105
}
106

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.