-
Notifications
You must be signed in to change notification settings - Fork 0
/
wrapper.go
101 lines (95 loc) · 2.33 KB
/
wrapper.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
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
package wrapper
import (
"github.com/ArcticOJ/blizzard/v0/logger"
rice "github.com/GeertJohan/go.rice"
"github.com/labstack/echo/v4"
"io"
"io/fs"
"mime"
"path"
"regexp"
"strconv"
"strings"
)
type RouteMap = map[string]string
func Traverse(box *rice.Box) (files []string, err error) {
if err := box.Walk(".", func(path string, inf fs.FileInfo, err error) error {
if inf.IsDir() {
return nil
}
files = append(files, path)
return nil
}); err != nil {
return nil, err
}
return files, nil
}
func BuildRoutes(files []string) (routes RouteMap) {
routes = make(RouteMap)
pattern := regexp.MustCompile(`\[(?P<id>(\w+))]`)
for _, file := range files {
if strings.HasPrefix(file, "_next") {
routes[file] = file
continue
}
route := strings.TrimPrefix(
strings.TrimSuffix(
strings.ReplaceAll(file, "/index.html", "/"),
".html"),
"bundle")
if _, fname := path.Split(route); strings.HasPrefix(fname, "._") {
continue
}
if sub := pattern.FindStringSubmatch(route); len(sub) > 0 {
param := sub[pattern.SubexpIndex("id")]
tPath := pattern.ReplaceAllLiteralString(route, ":"+param)
routes[tPath] = file
} else {
if route == "index" {
route = "/"
}
routes[route] = file
}
}
return
}
func ServeFile(box *rice.Box, c echo.Context, name string, mime string, is404 bool) error {
f, e := box.Open(name)
if e != nil {
if !is404 {
return ServeFile(box, c, "404.html", "text/html", true)
}
return e
}
defer f.Close()
h := c.Response().Header()
stat, _e := f.Stat()
if _e == nil {
h.Set("Content-Length", strconv.FormatInt(stat.Size(), 10))
h.Set("Last-Modified", stat.ModTime().UTC().Format("Wed, 21 Oct 2015 07:28:00 GMT"))
}
h.Set("Content-Type", mime)
buf, _ := io.ReadAll(f)
_, err := c.Response().Write(buf)
return err
}
func Register(ec *echo.Echo, bundle *rice.Box) {
if files, e := Traverse(bundle); e == nil {
routes := BuildRoutes(files)
for k, v := range routes {
x := v
t := "text/html"
if strings.HasPrefix(k, "_next") {
t = mime.TypeByExtension(path.Ext(x))
}
ec.GET(k, func(c echo.Context) error {
return ServeFile(bundle, c, x, t, k == "404")
})
}
ec.RouteNotFound("/*", func(c echo.Context) error {
return ServeFile(bundle, c, "404.html", "text/html", true)
})
} else {
logger.Panic(e, "failed to load embedded web bundle")
}
}