Francesco Siddi
9948fdab71
This commit does not introduce functional changes, besides renaming every mention of 'wizard' with 'setup assistant'. In order to run the manager setup assistant use: ./flamenco-manager -setup-assistant The change was introduced to favor more neutral and descriptive working for this functionality. Thanks to Sybren for helping to get this done!
80 lines
2.2 KiB
Go
80 lines
2.2 KiB
Go
package web
|
|
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
import (
|
|
"embed"
|
|
"errors"
|
|
"fmt"
|
|
"io/fs"
|
|
"mime"
|
|
"net/http"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
//go:embed static
|
|
var webStaticFS embed.FS
|
|
|
|
// WebAppHandler returns a HTTP handler to serve the static files of the Flamenco Manager web app.
|
|
// `appFilename` is either `index.html` for the main webapp, or `setup-assistant.html`.
|
|
func WebAppHandler(appFilename string) (http.Handler, error) {
|
|
// Strip the 'static/' directory off of the embedded filesystem.
|
|
fs, err := fs.Sub(webStaticFS, "static")
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to wrap embedded filesystem: %w", err)
|
|
}
|
|
|
|
// Serve `index.html` from the root directory if the requested file cannot be
|
|
// found. This is necessary for Vue Router, see the docstring of `FSWrapper`
|
|
// below.
|
|
wrappedFS := WrapFS(fs, appFilename)
|
|
|
|
// Windows doesn't know this mime type. Web browsers won't load the webapp JS
|
|
// file when it's served as text/plain.
|
|
if err := mime.AddExtensionType(".js", "application/javascript"); err != nil {
|
|
return nil, fmt.Errorf("registering mime type for JavaScript files: %w", err)
|
|
}
|
|
|
|
return http.FileServer(http.FS(wrappedFS)), nil
|
|
}
|
|
|
|
// FSWrapper wraps a filesystem and falls back to serving a specific file when
|
|
// the requested file cannot be found.
|
|
//
|
|
// This is necesasry for compatibility with Vue Router, as that generates URL
|
|
// paths to files that don't exist on the filesystem, like
|
|
// `/workers/c441766a-5d28-47cb-9589-b0caa4269065`. Serving `/index.html` in
|
|
// such cases makes Vue Router understand what's going on again.
|
|
type FSWrapper struct {
|
|
fs fs.FS
|
|
fallback string
|
|
}
|
|
|
|
func (w *FSWrapper) Open(name string) (fs.File, error) {
|
|
file, err := w.fs.Open(name)
|
|
|
|
switch {
|
|
case err == nil:
|
|
return file, nil
|
|
case errors.Is(err, fs.ErrNotExist):
|
|
fallbackFile, fallbackErr := w.fs.Open(w.fallback)
|
|
if fallbackErr != nil {
|
|
log.Error().
|
|
Str("name", name).
|
|
Str("fallback", w.fallback).
|
|
Err(err).
|
|
Str("fallbackErr", fallbackErr.Error()).
|
|
Msg("static web server: error opening fallback file")
|
|
return file, err
|
|
}
|
|
return fallbackFile, nil
|
|
}
|
|
|
|
return file, err
|
|
}
|
|
|
|
func WrapFS(fs fs.FS, fallback string) *FSWrapper {
|
|
return &FSWrapper{fs: fs, fallback: fallback}
|
|
}
|