This repository has been archived by the owner on Jan 6, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathtemplate.ego
139 lines (125 loc) · 3.86 KB
/
template.ego
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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
<%
package main
import (
"fmt"
"encoding/hex"
)
func GenerateTemplate(w io.Writer, pkg string, files []*file, buildTags string) error {
if buildTags != "" { %>
// +build <%== buildTags %>
<% } %>package <%== pkg %>
import (
"compress/gzip"
"fmt"
"io"
"io/ioutil"
"net/http"
"strconv"
"strings"
"time"
)
type staticFilesFile struct {
data string
mime string
mtime time.Time
// size is the size before compression. If 0, it means the data is uncompressed
size int
// hash is a sha256 hash of the file contents. Used for the Etag, and useful for caching
hash string
}
var staticFiles = map[string]*staticFilesFile{<% for _, f := range files { %>
<% _, _ = fmt.Fprintf(w, "%q", f.name) %>: {
data: <% _, _ = fmt.Fprintf(w, "%q", f.data) %>,
hash: <% _, _ = fmt.Fprintf(w, "%q", hex.EncodeToString(f.hash)) %>,
mime: <% _, _ = fmt.Fprintf(w, "%q", f.mime) %>,
mtime: time.Unix(<%== f.mtime.Unix() %>, 0),
size: <%== f.size %>,
},<% } %>
}
// NotFound is called when no asset is found.
// It defaults to http.NotFound but can be overwritten
var NotFound = http.NotFound
// ServeHTTP serves a request, attempting to reply with an embedded file.
func ServeHTTP(rw http.ResponseWriter, req *http.Request) {
path := strings.TrimPrefix(req.URL.Path, "/")
f, ok := staticFiles[path]
if !ok {
if path != "" && !strings.HasSuffix(path, "/") {
NotFound(rw, req)
return
}
f, ok = staticFiles[path + "index.html"]
if !ok {
NotFound(rw, req)
return
}
}
header := rw.Header()
if f.hash != "" {
if hash := req.Header.Get("If-None-Match"); hash == f.hash {
rw.WriteHeader(http.StatusNotModified)
return
}
header.Set("ETag", f.hash)
}
if !f.mtime.IsZero() {
if t, err := time.Parse(http.TimeFormat, req.Header.Get("If-Modified-Since")); err == nil && f.mtime.Before(t.Add(1*time.Second)) {
rw.WriteHeader(http.StatusNotModified)
return
}
header.Set("Last-Modified", f.mtime.UTC().Format(http.TimeFormat))
}
header.Set("Content-Type", f.mime)
// Check if the asset is compressed in the binary
if f.size == 0 {
header.Set("Content-Length", strconv.Itoa(len(f.data)))
io.WriteString(rw, f.data)
} else {
if header.Get("Content-Encoding") == "" && strings.Contains(req.Header.Get("Accept-Encoding"), "gzip") {
header.Set("Content-Encoding", "gzip")
header.Set("Content-Length", strconv.Itoa(len(f.data)))
io.WriteString(rw, f.data)
} else {
header.Set("Content-Length", strconv.Itoa(f.size))
reader, _ := gzip.NewReader(strings.NewReader(f.data))
io.Copy(rw, reader)
reader.Close()
}
}
}
// Server is simply ServeHTTP but wrapped in http.HandlerFunc so it can be passed into net/http functions directly.
var Server http.Handler = http.HandlerFunc(ServeHTTP)
// Open allows you to read an embedded file directly. It will return a decompressing Reader if the file is embedded in compressed format.
// You should close the Reader after you're done with it.
func Open(name string) (io.ReadCloser, error) {
f, ok := staticFiles[name]
if !ok {
return nil, fmt.Errorf("Asset %s not found", name)
}
if f.size == 0 {
return ioutil.NopCloser(strings.NewReader(f.data)), nil
}
return gzip.NewReader(strings.NewReader(f.data))
}
// ModTime returns the modification time of the original file.
// Useful for caching purposes
// Returns zero time if the file is not in the bundle
func ModTime(file string) (t time.Time) {
if f, ok := staticFiles[file]; ok {
t = f.mtime
}
return
}
// Hash returns the hex-encoded SHA256 hash of the original file
// Used for the Etag, and useful for caching
// Returns an empty string if the file is not in the bundle
func Hash(file string) (s string) {
if f, ok := staticFiles[file]; ok {
s = f.hash
}
return
}
<%
return nil
}
%>