2021-08-22 23:05:22 +10:00
package assetserver
import (
"bytes"
2021-10-10 15:43:01 +11:00
"errors"
2022-04-12 12:18:27 +02:00
"io"
"net/http"
2023-11-12 12:30:49 +11:00
"strconv"
2022-07-24 20:20:02 +10:00
"strings"
2021-08-22 23:05:22 +10:00
2022-10-29 23:15:15 +02:00
"github.com/wailsapp/wails/v2/pkg/options"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
2022-03-30 15:40:44 +02:00
"golang.org/x/net/html"
)
2021-10-02 14:04:46 +10:00
2022-11-29 09:29:08 +01:00
func BuildAssetServerConfig ( appOptions * options . App ) ( assetserver . Options , error ) {
var options assetserver . Options
if opt := appOptions . AssetServer ; opt != nil {
if appOptions . Assets != nil || appOptions . AssetsHandler != nil {
2022-10-29 23:15:15 +02:00
panic ( "It's not possible to use the deprecated Assets and AssetsHandler options and the new AssetServer option at the same time. Please migrate all your Assets options to the AssetServer option." )
}
2022-11-29 09:29:08 +01:00
options = * opt
} else {
options = assetserver . Options {
Assets : appOptions . Assets ,
Handler : appOptions . AssetsHandler ,
}
2022-10-29 23:15:15 +02:00
}
2022-11-29 09:29:08 +01:00
return options , options . Validate ()
2022-10-29 23:15:15 +02:00
}
2021-10-02 14:04:46 +10:00
const (
2022-04-12 12:18:27 +02:00
HeaderHost = "Host"
2022-03-30 15:40:44 +02:00
HeaderContentType = "Content-Type"
HeaderContentLength = "Content-Length"
HeaderUserAgent = "User-Agent"
HeaderCacheControl = "Cache-Control"
2022-07-24 20:20:02 +10:00
HeaderUpgrade = "Upgrade"
2022-03-30 15:40:44 +02:00
WailsUserAgentValue = "wails.io"
2021-10-02 14:04:46 +10:00
)
2022-04-12 12:18:27 +02:00
func serveFile ( rw http . ResponseWriter , filename string , blob [] byte ) error {
header := rw . Header ()
2023-11-12 12:30:49 +11:00
header . Set ( HeaderContentLength , strconv . Itoa ( len ( blob )))
2022-04-12 12:18:27 +02:00
if mimeType := header . Get ( HeaderContentType ); mimeType == "" {
mimeType = GetMimetype ( filename , blob )
header . Set ( HeaderContentType , mimeType )
}
rw . WriteHeader ( http . StatusOK )
_ , err := io . Copy ( rw , bytes . NewReader ( blob ))
return err
}
2021-10-10 15:43:01 +11:00
func createScriptNode ( scriptName string ) * html . Node {
return & html . Node {
Type : html . ElementNode ,
Data : "script" ,
Attr : [] html . Attribute {
{
Key : "src" ,
Val : scriptName ,
},
},
}
}
func createDivNode ( id string ) * html . Node {
return & html . Node {
Type : html . ElementNode ,
Data : "div" ,
Attr : [] html . Attribute {
{
Namespace : "" ,
Key : "id" ,
Val : id ,
},
},
}
}
func insertScriptInHead ( htmlNode * html . Node , scriptName string ) error {
headNode := findFirstTag ( htmlNode , "head" )
if headNode == nil {
return errors . New ( "cannot find head in HTML" )
}
scriptNode := createScriptNode ( scriptName )
if headNode . FirstChild != nil {
headNode . InsertBefore ( scriptNode , headNode . FirstChild )
} else {
headNode . AppendChild ( scriptNode )
}
return nil
}
func appendSpinnerToBody ( htmlNode * html . Node ) error {
bodyNode := findFirstTag ( htmlNode , "body" )
if bodyNode == nil {
return errors . New ( "cannot find body in HTML" )
}
scriptNode := createDivNode ( "wails-spinner" )
bodyNode . AppendChild ( scriptNode )
return nil
}
func getHTMLNode ( htmldata [] byte ) ( * html . Node , error ) {
return html . Parse ( bytes . NewReader ( htmldata ))
}
func findFirstTag ( htmlnode * html . Node , tagName string ) * html . Node {
var extractor func ( * html . Node ) * html . Node
var result * html . Node
extractor = func ( node * html . Node ) * html . Node {
if node . Type == html . ElementNode && node . Data == tagName {
return node
}
for child := node . FirstChild ; child != nil ; child = child . NextSibling {
result := extractor ( child )
if result != nil {
return result
}
}
return nil
}
result = extractor ( htmlnode )
return result
}
2022-07-24 20:20:02 +10:00
func isWebSocket ( req * http . Request ) bool {
upgrade := req . Header . Get ( HeaderUpgrade )
return strings . EqualFold ( upgrade , "websocket" )
}