5
0
mirror of https://github.com/wailsapp/wails.git synced 2025-05-02 14:10:25 +08:00
wails/v2/pkg/assetserver/assethandler_external.go
Lea Anthony c1c4220978
V2 features/proxy to external server (#3463)
* Add NewProxyServer function

* Pass through all methods for mac

* Content length fix

* Update changelog.mdx

* Update deps
2024-05-08 20:39:49 +10:00

90 lines
1.9 KiB
Go

package assetserver
import (
"errors"
"fmt"
"net/http"
"net/http/httputil"
"net/url"
"runtime"
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
)
func NewProxyServer(proxyURL string) http.Handler {
parsedURL, err := url.Parse(proxyURL)
if err != nil {
panic(err)
}
return NewExternalAssetsHandler(nil,
assetserver.Options{},
parsedURL)
}
func NewExternalAssetsHandler(logger Logger, options assetserver.Options, url *url.URL) http.Handler {
baseHandler := options.Handler
errSkipProxy := fmt.Errorf("skip proxying")
proxy := httputil.NewSingleHostReverseProxy(url)
baseDirector := proxy.Director
proxy.Director = func(r *http.Request) {
baseDirector(r)
if logger != nil {
logger.Debug("[ExternalAssetHandler] Loading '%s'", r.URL)
}
}
proxy.ModifyResponse = func(res *http.Response) error {
if baseHandler == nil {
return nil
}
if res.StatusCode == http.StatusSwitchingProtocols {
return nil
}
if res.StatusCode == http.StatusNotFound || res.StatusCode == http.StatusMethodNotAllowed {
return errSkipProxy
}
return nil
}
proxy.ErrorHandler = func(rw http.ResponseWriter, r *http.Request, err error) {
if baseHandler != nil && errors.Is(err, errSkipProxy) {
if logger != nil {
logger.Debug("[ExternalAssetHandler] '%s' returned not found, using AssetHandler", r.URL)
}
baseHandler.ServeHTTP(rw, r)
} else {
if logger != nil {
logger.Error("[ExternalAssetHandler] Proxy error: %v", err)
}
rw.WriteHeader(http.StatusBadGateway)
}
}
var result http.Handler = http.HandlerFunc(
func(rw http.ResponseWriter, req *http.Request) {
if runtime.GOOS == "darwin" || req.Method == http.MethodGet {
proxy.ServeHTTP(rw, req)
return
}
if baseHandler != nil {
baseHandler.ServeHTTP(rw, req)
return
}
rw.WriteHeader(http.StatusMethodNotAllowed)
})
if middleware := options.Middleware; middleware != nil {
result = middleware(result)
}
return result
}