Skip to content

Commit 5b6236c

Browse files
feat(web): compress assets
1 parent 2556945 commit 5b6236c

File tree

6 files changed

+55
-50
lines changed

6 files changed

+55
-50
lines changed

cmd/smtpbridge/main.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"github.com/ItsNotGoodName/smtpbridge/web"
2424
"github.com/ItsNotGoodName/smtpbridge/web/helpers"
2525
"github.com/ItsNotGoodName/smtpbridge/web/http"
26+
"github.com/ItsNotGoodName/smtpbridge/web/session"
2627
"github.com/Rican7/lieut"
2728
"github.com/gorilla/sessions"
2829
"github.com/reugn/go-quartz/quartz"
@@ -170,18 +171,21 @@ func run(flags *flag.FlagSet) lieut.Executor {
170171

171172
// HTTP
172173
if !cfg.HTTPDisable {
174+
// HTTP CSRF
173175
csrfSecret, err := secret.GetOrCreate(cfg.CSRFSecretPath)
174176
if err != nil {
175177
return err
176178
}
177179

180+
// HTTP session
178181
sessionSecret, err := secret.GetOrCreate(cfg.SessionSecretPath)
179182
if err != nil {
180183
return err
181184
}
185+
sessionStore := sessions.NewFilesystemStore(cfg.SessionsDirectory, sessionSecret)
186+
session.ConfigureOptions(sessionStore.Options)
182187

183188
controller := http.NewController(app, cfg.TimeHourFormat)
184-
sessionStore := sessions.NewFilesystemStore(cfg.SessionsDirectory, sessionSecret)
185189
router := http.NewRouter(controller, app, fileStore, csrfSecret, sessionStore)
186190
server := http.NewServer(router, cfg.HTTPAddress)
187191
super.Add(server)

web/http/router.go

+15-40
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
11
package http
22

33
import (
4+
"compress/flate"
45
"io/fs"
5-
"net/http"
66

77
"github.com/ItsNotGoodName/smtpbridge/internal/core"
8+
"github.com/ItsNotGoodName/smtpbridge/pkg/chiext"
89
"github.com/ItsNotGoodName/smtpbridge/web"
910
"github.com/ItsNotGoodName/smtpbridge/web/pages"
1011
"github.com/ItsNotGoodName/smtpbridge/web/routes"
11-
"github.com/ItsNotGoodName/smtpbridge/web/sessions"
12+
"github.com/ItsNotGoodName/smtpbridge/web/session"
1213
"github.com/go-chi/chi/v5"
1314
"github.com/go-chi/chi/v5/middleware"
1415
"github.com/gorilla/csrf"
16+
"github.com/gorilla/sessions"
1517
)
1618

1719
const paramID = "{id}"
@@ -25,20 +27,27 @@ func NewRouter(ct pages.Controller, app core.App, fileFS fs.FS, csrfSecret []byt
2527
r.Use(middleware.Recoverer)
2628
r.Use(csrf.Protect(csrfSecret, csrf.Secure(false), csrf.Path("/")))
2729

28-
mountWebFS(r, web.FS)
30+
r.Group(func(r chi.Router) {
31+
r.Use(web.CacheControl)
32+
r.Use(middleware.NewCompressor(flate.DefaultCompression, "application/javascript", "text/css").Handler)
33+
34+
chiext.MountFS(r, web.FS)
35+
})
2936

30-
// Login
37+
// Unauthorized
3138
r.Group(func(r chi.Router) {
32-
r.Use(sessions.AuthRestrict(app, ss))
39+
r.Use(session.AuthRestrict(app, ss))
3340

41+
// Login
3442
r.Get(routes.Login().String(),
3543
pages.LoginView(ct, app))
3644
r.Post(routes.Login().String(),
3745
pages.Login(ct, app, ss))
3846
})
3947

48+
// Authorized
4049
r.Group(func(r chi.Router) {
41-
r.Use(sessions.AuthRequire(app, ss))
50+
r.Use(session.AuthRequire(app, ss))
4251

4352
// Logout
4453
r.Delete(routes.Logout().String(),
@@ -134,37 +143,3 @@ func NewRouter(ct pages.Controller, app core.App, fileFS fs.FS, csrfSecret []byt
134143

135144
return r
136145
}
137-
138-
func mountWebFS(r chi.Router, f fs.FS) error {
139-
fsHandler := http.StripPrefix("/", http.FileServer(http.FS(f)))
140-
141-
normalFS := func(w http.ResponseWriter, r *http.Request) {
142-
w.Header().Set("Cache-Control", "max-age=3600")
143-
fsHandler.ServeHTTP(w, r)
144-
}
145-
146-
// Files in assets have a hash
147-
assetsFS := func(w http.ResponseWriter, r *http.Request) {
148-
w.Header().Set("Cache-Control", "max-age=31536000,immutable")
149-
fsHandler.ServeHTTP(w, r)
150-
}
151-
152-
if files, err := fs.ReadDir(f, "."); err == nil {
153-
for _, f := range files {
154-
name := f.Name()
155-
if f.IsDir() {
156-
if name == "assets" {
157-
r.Get("/"+name+"/*", assetsFS)
158-
} else {
159-
r.Get("/"+name+"/*", normalFS)
160-
}
161-
} else {
162-
r.Get("/"+name, normalFS)
163-
}
164-
}
165-
} else if err != fs.ErrNotExist {
166-
return err
167-
}
168-
169-
return nil
170-
}

web/pages/pages.go

+4-3
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@ import (
2323
"github.com/ItsNotGoodName/smtpbridge/web/helpers"
2424
"github.com/ItsNotGoodName/smtpbridge/web/meta"
2525
"github.com/ItsNotGoodName/smtpbridge/web/routes"
26-
"github.com/ItsNotGoodName/smtpbridge/web/sessions"
26+
"github.com/ItsNotGoodName/smtpbridge/web/session"
2727
"github.com/a-h/templ"
2828
"github.com/go-chi/chi/v5"
29+
"github.com/gorilla/sessions"
2930
"github.com/kballard/go-shellquote"
3031
"github.com/samber/lo"
3132
)
@@ -313,7 +314,7 @@ func Login(ct Controller, app core.App, ss sessions.Store) http.HandlerFunc {
313314
return
314315
}
315316

316-
err = sessions.AuthLogin(w, r, ss, user.ID)
317+
err = session.AuthLogin(w, r, ss, user.ID)
317318
if err != nil {
318319
handleErr(w, r, err, form)
319320
return
@@ -325,7 +326,7 @@ func Login(ct Controller, app core.App, ss sessions.Store) http.HandlerFunc {
325326

326327
func Logout(ct Controller, app core.App, ss sessions.Store) http.HandlerFunc {
327328
return func(w http.ResponseWriter, r *http.Request) {
328-
err := sessions.AuthLogout(w, r, ss)
329+
err := session.AuthLogout(w, r, ss)
329330
if err != nil {
330331
ct.Error(w, r, err, http.StatusInternalServerError)
331332
return

web/sessions/auth.go web/session/auth.go

+4-6
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package sessions
1+
package session
22

33
import (
44
"net/http"
@@ -9,17 +9,15 @@ import (
99
"github.com/gorilla/sessions"
1010
)
1111

12-
type Store = sessions.Store
13-
14-
func AuthLogin(w http.ResponseWriter, r *http.Request, ss Store, id int64) error {
12+
func AuthLogin(w http.ResponseWriter, r *http.Request, ss sessions.Store, id int64) error {
1513
session, _ := ss.New(r, "auth")
1614

1715
session.Values["id"] = id
1816

1917
return ss.Save(r, w, session)
2018
}
2119

22-
func AuthLogout(w http.ResponseWriter, r *http.Request, ss Store) error {
20+
func AuthLogout(w http.ResponseWriter, r *http.Request, ss sessions.Store) error {
2321
session, _ := ss.Get(r, "auth")
2422

2523
delete(session.Values, "id")
@@ -49,7 +47,7 @@ func AuthRequire(app core.App, ss sessions.Store) func(http.Handler) http.Handle
4947
}
5048
}
5149

52-
func AuthRestrict(app core.App, ss Store) func(http.Handler) http.Handler {
50+
func AuthRestrict(app core.App, ss sessions.Store) func(http.Handler) http.Handler {
5351
return func(h http.Handler) http.Handler {
5452
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
5553
if app.AuthHTTPAnonymous() {

web/session/session.go

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
package session
2+
3+
import (
4+
"net/http"
5+
6+
"github.com/gorilla/sessions"
7+
)
8+
9+
func ConfigureOptions(opts *sessions.Options) {
10+
opts.SameSite = http.SameSiteLaxMode
11+
opts.HttpOnly = true
12+
}

web/web.go

+15
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ import (
55
"context"
66
"io/fs"
77
"mime"
8+
"net/http"
89
"path/filepath"
10+
"strings"
911

1012
"github.com/thejerf/suture/v4"
1113
)
@@ -43,3 +45,16 @@ func (r Refresher) Serve(ctx context.Context) error {
4345
reloadVite()
4446
return suture.ErrDoNotRestart
4547
}
48+
49+
func CacheControl(h http.Handler) http.Handler {
50+
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
51+
if strings.HasPrefix(r.RequestURI, "/assets") {
52+
// Files in assets have a hash associated with them
53+
w.Header().Set("Cache-Control", "max-age=31536000,immutable")
54+
} else {
55+
w.Header().Set("Cache-Control", "max-age=3600")
56+
}
57+
58+
h.ServeHTTP(w, r)
59+
})
60+
}

0 commit comments

Comments
 (0)