mirror of
https://github.com/wailsapp/wails.git
synced 2025-05-02 23:02:19 +08:00

* [v2] Consolidate AssetServers * [v2] Support starturl for webview on linux and darwin * [v2] Add support for frontend DevServer * [v2] Activate frontend DevServer in svelte template * [website] Add bleeding edge guide for PRs * DoNotMerge: Bump Version for testing Co-authored-by: Lea Anthony <lea.anthony@gmail.com>
125 lines
2.6 KiB
Go
125 lines
2.6 KiB
Go
package assetserver
|
|
|
|
import (
|
|
"context"
|
|
_ "embed"
|
|
iofs "io/fs"
|
|
"net/http"
|
|
"os"
|
|
"path"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/wailsapp/wails/v2/internal/fs"
|
|
"github.com/wailsapp/wails/v2/internal/logger"
|
|
"github.com/wailsapp/wails/v2/pkg/options"
|
|
)
|
|
|
|
//go:embed defaultindex.html
|
|
var defaultHTML []byte
|
|
|
|
type assetHandler struct {
|
|
fs iofs.FS
|
|
|
|
logger *logger.Logger
|
|
|
|
servingFromDisk bool
|
|
}
|
|
|
|
func NewAsssetHandler(ctx context.Context, options *options.App) (http.Handler, error) {
|
|
vfs := options.Assets
|
|
if vfs != nil {
|
|
if _, err := vfs.Open("."); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
subDir, err := fs.FindPathToFile(vfs, "index.html")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
vfs, err = iofs.Sub(vfs, path.Clean(subDir))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
result := &assetHandler{
|
|
fs: vfs,
|
|
|
|
// Check if we have been given a directory to serve assets from.
|
|
// If so, this means we are in dev mode and are serving assets off disk.
|
|
// We indicate this through the `servingFromDisk` flag to ensure requests
|
|
// aren't cached in dev mode.
|
|
servingFromDisk: ctx.Value("assetdir") != nil,
|
|
}
|
|
|
|
if _logger := ctx.Value("logger"); _logger != nil {
|
|
result.logger = _logger.(*logger.Logger)
|
|
}
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (d *assetHandler) ServeHTTP(rw http.ResponseWriter, req *http.Request) {
|
|
if d.fs == nil {
|
|
rw.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
filename := strings.TrimPrefix(req.URL.Path, "/")
|
|
if d.logger != nil {
|
|
d.logger.Debug("[AssetHandler] Loading file '%s'", filename)
|
|
}
|
|
|
|
var content []byte
|
|
var err error
|
|
switch filename {
|
|
case "", "index.html":
|
|
content, err = d.loadFile("index.html")
|
|
if err != nil {
|
|
err = nil
|
|
content = defaultHTML
|
|
}
|
|
|
|
default:
|
|
content, err = d.loadFile(filename)
|
|
}
|
|
|
|
if os.IsNotExist(err) {
|
|
rw.WriteHeader(http.StatusNotFound)
|
|
return
|
|
}
|
|
|
|
if err == nil {
|
|
mimeType := GetMimetype(filename, content)
|
|
rw.Header().Set(HeaderContentType, mimeType)
|
|
rw.WriteHeader(http.StatusOK)
|
|
_, err = rw.Write(content)
|
|
}
|
|
|
|
if err != nil {
|
|
rw.WriteHeader(http.StatusInternalServerError)
|
|
if d.logger != nil {
|
|
d.logger.Error("[AssetHandler] Unable to load file '%s': %s", filename, err)
|
|
}
|
|
}
|
|
}
|
|
|
|
// loadFile will try to load the file from disk. If there is an error
|
|
// it will retry until eventually it will give up and error.
|
|
func (d *assetHandler) loadFile(filename string) ([]byte, error) {
|
|
if !d.servingFromDisk {
|
|
return iofs.ReadFile(d.fs, filename)
|
|
}
|
|
var result []byte
|
|
var err error
|
|
for tries := 0; tries < 50; tries++ {
|
|
result, err = iofs.ReadFile(d.fs, filename)
|
|
if err != nil {
|
|
time.Sleep(100 * time.Millisecond)
|
|
}
|
|
}
|
|
return result, err
|
|
}
|