-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgolatt.go
136 lines (122 loc) · 3.64 KB
/
golatt.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
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
package golatt
import (
"context"
"embed"
"github.com/gorilla/mux"
"html/template"
"io/fs"
"log/slog"
"net/http"
"os"
"os/signal"
"time"
)
// Golatt is a http server empowered by mux.Router
type Golatt struct {
// Router used
*mux.Router
// Files containing templates used
Files fs.FS
// Templates to parse during a request
Templates []string
// DefaultSeoData contains all default seo data used by opengraph and twitter
DefaultSeoData *SeoData
// InitialSection is the initial section called to render templates.
// It must be the section containing basic HTML5 structure
//
// Default: "base"
InitialSection string
// FormatTitle format titles to be more consistant.
//
// Default: returns the title without modification
FormatTitle func(t string) string
// AssetsFS is the filesystem containing all the assets. It must start with AssetsName
AssetsFS fs.FS
// StaticFS is the filesystem containing all the static files. It must start with StaticName
StaticFS fs.FS
// PageDirectory is the folder containing page templates
//
// Default: "page"
PageDirectory string
// TemplateExtension is the extension of all templates
//
// Default: "gohtml"
TemplateExtension string
// NotFoundHandler handles 404 errors
NotFoundHandler func(http.ResponseWriter, *http.Request)
// TemplateFuncMap is a map of custom functions usable in templates
TemplateFuncMap template.FuncMap
}
// New creates a new Golatt instance with provided files (must be valid go templates files)
//
// If you are providing an embed.FS, check UsableEmbedFS before passing this argument
func New(files fs.FS, static fs.FS, assets fs.FS) *Golatt {
return &Golatt{
Files: files,
Router: mux.NewRouter(),
FormatTitle: func(t string) string {
return t
},
Templates: make([]string, 0),
InitialSection: "base",
AssetsFS: assets,
StaticFS: static,
PageDirectory: "page",
TemplateExtension: "gohtml",
NotFoundHandler: http.NotFound,
TemplateFuncMap: template.FuncMap{},
}
}
// StartServer starts the http server listening on addr (e.g. ":8000", "127.0.0.1:80")
func (g *Golatt) StartServer(addr string) {
g.PathPrefix("/static/").Handler(http.StripPrefix("/static/", http.FileServerFS(g.StaticFS)))
g.PathPrefix("/assets/").Handler(http.StripPrefix("/assets/", http.FileServerFS(g.AssetsFS)))
g.Router.NotFoundHandler = http.HandlerFunc(g.NotFoundHandler)
srv := &http.Server{
Handler: g,
Addr: addr,
WriteTimeout: 15 * time.Second,
ReadTimeout: 15 * time.Second,
}
slog.Info("Starting...")
go func() {
if err := srv.ListenAndServe(); err != nil {
slog.Error(err.Error())
}
}()
slog.Info("Started")
slog.Info("Listening on " + srv.Addr)
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
<-c
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
defer cancel()
err := srv.Shutdown(ctx)
if err != nil {
panic(err)
}
slog.Info("Shutting down")
}
// httpEmbedFS is an implementation of fs.FS, fs.ReadDirFS and fs.ReadFileFS helping to manage embed.FS for http server
type httpEmbedFS struct {
prefix string
embed.FS
}
func (h *httpEmbedFS) Open(name string) (fs.File, error) {
return h.FS.Open(h.prefix + "/" + name)
}
func (h *httpEmbedFS) ReadFile(name string) ([]byte, error) {
return h.FS.ReadFile(h.prefix + "/" + name)
}
func (h *httpEmbedFS) ReadDir(name string) ([]fs.DirEntry, error) {
return h.FS.ReadDir(h.prefix + "/" + name)
}
// UsableEmbedFS converts embed.FS into usable fs.FS by Golatt
//
// folder may not finish or start with a slash (/)
func UsableEmbedFS(folder string, em embed.FS) fs.FS {
return &httpEmbedFS{
prefix: folder,
FS: em,
}
}