fix(web): PWA asset and route handling (#898)

* fix(web): PWA asset and fallback route handling

* fix(web): strip baseurl

* fix(web): add back manifest.json

* fix(web): add back manifest.json

* fix(web): log file

* fix(web): do not trim baseurl

* fix(web): try different start_url

* fix(web): pwa with subfolder
This commit is contained in:
ze0s 2023-05-02 19:06:53 +02:00 committed by GitHub
parent d085d894d4
commit 319bc2f200
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 110 additions and 30 deletions

View file

@ -3,6 +3,7 @@ node_modules/
.gitignore
.github
.dev
dev/
config.toml
.goreleaser.yml
Dockerfile
@ -12,18 +13,18 @@ README.md
bin
config
test
web/*
!web/public
!web/src
!web/dist*
!web/package.json
!web/yarn.lock
!web/.yarnrc.yml
!web/.yarn/releases
!web/.eslintrc.js
!web/postcss.config.js
!web/tailwind.config.js
!web/tsconfig.json
!web/index.html
!web/vite.config.ts
!web/build.go
#web/*
#!web/public
#!web/src
#!web/dist*
#!web/package.json
#!web/yarn.lock
#!web/.yarnrc.yml
#!web/.yarn/releases
#!web/.eslintrc.js
#!web/postcss.config.js
#!web/tailwind.config.js
#!web/tsconfig.json
#!web/index.html
#!web/vite.config.ts
#!web/build.go

View file

@ -108,7 +108,6 @@ func (s Server) Handler() http.Handler {
r.Use(c.Handler)
encoder := encoder{}
web.RegisterHandler(r)
r.Route("/api", func(r chi.Router) {
r.Route("/auth", newAuthHandler(encoder, s.log, s.config.Config, s.cookieStore, s.authService).Routes)
@ -145,9 +144,8 @@ func (s Server) Handler() http.Handler {
})
})
// serve the parsed index.html
r.Get("/", s.index)
r.Get("/*", s.index)
// serve the web
web.RegisterHandler(r, s.version, s.config.Config.BaseURL)
return r
}

View file

@ -14,6 +14,7 @@ import (
"net/http"
"os"
"path/filepath"
"strings"
"github.com/go-chi/chi/v5"
)
@ -92,6 +93,7 @@ func StaticFS(r *chi.Mux, pathPrefix string, filesystem fs.FS) {
// fsFile is a helper function to serve a file from the provided file system.
func fsFile(w http.ResponseWriter, r *http.Request, file string, filesystem fs.FS) {
//fmt.Printf("file: %s\n", file)
f, err := filesystem.Open(file)
if err != nil {
http.Error(w, "File not found", http.StatusNotFound)
@ -115,16 +117,74 @@ func fsFile(w http.ResponseWriter, r *http.Request, file string, filesystem fs.F
http.ServeContent(w, r, file, stat.ModTime(), reader)
}
func RegisterHandler(c *chi.Mux) {
var validRoutes = []string{"/", "filters", "releases", "settings", "logs", "onboard", "login", "logout"}
func validRoute(route string) bool {
for _, valid := range validRoutes {
if strings.Contains(route, valid) {
return true
}
}
return false
}
// RegisterHandler register web routes and file serving
func RegisterHandler(c *chi.Mux, version, baseUrl string) {
// Serve static files without a prefix
assets, _ := fs.Sub(DistDirFS, "assets")
static, _ := fs.Sub(DistDirFS, "static")
StaticFS(c, "/assets", assets)
StaticFS(c, "/static", static)
p := IndexParams{
Title: "Dashboard",
Version: version,
BaseUrl: baseUrl,
}
// serve on base route
c.Get("/", func(w http.ResponseWriter, r *http.Request) {
Index(w, p)
})
// handle all other routes
c.Get("/*", func(w http.ResponseWriter, r *http.Request) {
// Serve index.html for unmatched routes
fsFile(w, r, "dist/index.html", Dist)
file := strings.TrimPrefix(r.RequestURI, "/")
// if valid web route then serve html
if validRoute(file) || file == "index.html" {
Index(w, p)
return
}
if strings.Contains(file, "manifest.webmanifest") {
Manifest(w, p)
return
}
// if not valid web route then try and serve files
f, err := DistDirFS.Open(file)
if err != nil {
http.Error(w, "File not found", http.StatusNotFound)
return
}
defer f.Close()
stat, err := f.Stat()
if err != nil {
http.Error(w, "File not found", http.StatusNotFound)
return
}
data, err := io.ReadAll(f)
if err != nil {
http.Error(w, "Failed to read the file", http.StatusInternalServerError)
return
}
reader := bytes.NewReader(data)
http.ServeContent(w, r, file, stat.ModTime(), reader)
})
}
@ -135,3 +195,11 @@ func Index(w io.Writer, p IndexParams) error {
func parseIndex() *template.Template {
return template.Must(template.New("index.html").ParseFS(Dist, "dist/index.html"))
}
func Manifest(w io.Writer, p IndexParams) error {
return parseManifest().Execute(w, p)
}
func parseManifest() *template.Template {
return template.Must(template.New("manifest.webmanifest").ParseFS(Dist, "dist/manifest.webmanifest"))
}

View file

@ -19,7 +19,7 @@
<link rel="apple-touch-icon" sizes="60x60" href="/apple-touch-icon-ipad-76x76.png">
<link rel="apple-touch-icon" sizes="114x114" href="/apple-touch-icon-iphone-retina-120x120.png">
<link rel="apple-touch-icon" sizes="144x144" href="/apple-touch-icon-ipad-retina-152x152.png">
<link crossorigin="use-credentials" rel="manifest" href="/manifest.json" />
<!-- <link crossorigin="use-credentials" rel="manifest" href="/manifest.json" />-->
<title>autobrr</title>
<base href="{{.BaseUrl}}">
<script>

View file

@ -18,8 +18,8 @@
"sizes": "512x512"
}
],
"start_url": ".",
"start_url": "/",
"display": "standalone",
"theme_color": "#000000",
"background_color": "#ffffff"
}
}

BIN
web/public/logo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

View file

@ -13,12 +13,16 @@ export default ({ mode }: { mode: any }) => {
base: "",
plugins: [react(), VitePWA({
registerType: "autoUpdate",
injectRegister: "auto",
injectRegister: "inline",
scope: "{{.BaseUrl}}",
// strategies: "injectManifest",
useCredentials: true,
includeAssets: [
"favicon.svg",
"favicon.ico",
"robots.txt",
"apple-touch-icon.png",
"logo.png",
"apple-touch-icon-*.png",
"manifest.webmanifest",
"assets/**/*"
],
@ -29,6 +33,11 @@ export default ({ mode }: { mode: any }) => {
theme_color: "#141415",
background_color: "#141415",
icons: [
{
src: "logo.png",
sizes: "192x192",
type: "image/png"
},
{
src: "logo192.png",
sizes: "192x192",
@ -39,17 +48,21 @@ export default ({ mode }: { mode: any }) => {
sizes: "512x512",
type: "image/png"
},
{
src: "logo512.png",
sizes: "512x512",
type: "image/png",
purpose: "any maskable"
},
{
src: "apple-touch-icon-iphone-retina-120x120.png",
sizes: "120x120",
type: "image/png"
}
],
start_url: "/",
start_url: "{{.BaseUrl}}",
scope: "{{.BaseUrl}}",
display: "standalone"
},
workbox: {
globPatterns: ["**/*.{js,css,html,svg}"],