From 08bc342fd6739d082d70b5c6ea301e93eb8f02b5 Mon Sep 17 00:00:00 2001 From: josc146 Date: Tue, 26 Mar 2024 21:23:09 +0800 Subject: [PATCH] proxied fetch support --- backend-golang/app.go | 61 +++++++++++++++++++++ frontend/src/stores/commonStore.ts | 5 ++ frontend/src/utils/index.tsx | 18 ++++++ frontend/src/webWails.js | 6 ++ frontend/wailsjs/go/backend_golang/App.d.ts | 2 + frontend/wailsjs/go/backend_golang/App.js | 4 ++ 6 files changed, 96 insertions(+) diff --git a/backend-golang/app.go b/backend-golang/app.go index 7d65eb3..be2d89a 100644 --- a/backend-golang/app.go +++ b/backend-golang/app.go @@ -7,7 +7,11 @@ import ( "context" "errors" "io" + "log" + "net" "net/http" + "net/http/httputil" + "net/url" "os" "os/exec" "path/filepath" @@ -27,6 +31,7 @@ type App struct { HasConfigData bool ConfigData map[string]any Dev bool + proxyPort int exDir string cmdPrefix string } @@ -36,6 +41,57 @@ func NewApp() *App { return &App{} } +func (a *App) newFetchProxy() { + go func() { + handler := func(w http.ResponseWriter, r *http.Request) { + if r.Method == "OPTIONS" { + w.Header().Set("Access-Control-Allow-Methods", "GET, POST, OPTIONS") + w.Header().Set("Access-Control-Allow-Headers", "*") + w.Header().Set("Access-Control-Allow-Origin", "*") + return + } + proxy := &httputil.ReverseProxy{ + ModifyResponse: func(res *http.Response) error { + res.Header.Set("Access-Control-Allow-Origin", "*") + return nil + }, + Director: func(req *http.Request) { + realTarget := req.Header.Get("Real-Target") + if realTarget != "" { + target, err := url.Parse(realTarget) + if err != nil { + log.Printf("Error parsing target URL: %v\n", err) + return + } + req.Header.Set("Accept", "*/*") + req.Header.Del("Origin") + req.Header.Del("Referer") + req.Header.Del("Real-Target") + req.Header.Del("Sec-Fetch-Dest") + req.Header.Del("Sec-Fetch-Mode") + req.Header.Del("Sec-Fetch-Site") + req.URL.Scheme = target.Scheme + req.URL.Host = target.Host + req.URL.Path = target.Path + log.Println("Proxying to", realTarget) + } else { + log.Println("Real-Target header is missing") + } + }, + } + proxy.ServeHTTP(w, r) + } + http.HandleFunc("/", handler) + listener, err := net.Listen("tcp", "127.0.0.1:0") + if err != nil { + return + } + a.proxyPort = listener.Addr().(*net.TCPAddr).Port + + http.Serve(listener, nil) + }() +} + // startup is called when the app starts. The context is saved // so we can call the runtime methods func (a *App) OnStartup(ctx context.Context) { @@ -76,6 +132,7 @@ func (a *App) OnStartup(ctx context.Context) { a.midiLoop() a.watchFs() a.monitorHardware() + a.newFetchProxy() } func (a *App) OnBeforeClose(ctx context.Context) bool { @@ -239,3 +296,7 @@ func (a *App) RestartApp() error { func (a *App) GetPlatform() string { return runtime.GOOS } + +func (a *App) GetProxyPort() int { + return a.proxyPort +} diff --git a/frontend/src/stores/commonStore.ts b/frontend/src/stores/commonStore.ts index 67f31cc..ba60b60 100644 --- a/frontend/src/stores/commonStore.ts +++ b/frontend/src/stores/commonStore.ts @@ -63,6 +63,7 @@ class CommonStore { monitorData: MonitorData | null = null; depComplete: boolean = false; platform: Platform = 'windows'; + proxyPort: number = 0; lastModelName: string = ''; // presets manager editingPreset: Preset | null = null; @@ -323,6 +324,10 @@ class CommonStore { this.platform = value; } + setProxyPort(value: number) { + this.proxyPort = value; + } + setCurrentInput(value: string) { this.currentInput = value; } diff --git a/frontend/src/utils/index.tsx b/frontend/src/utils/index.tsx index 30144e6..5718acd 100644 --- a/frontend/src/utils/index.tsx +++ b/frontend/src/utils/index.tsx @@ -310,6 +310,24 @@ export function bytesToReadable(size: number) { else return bytesToGb(size) + ' GB'; } +export async function getReqUrl(port: number, path: string, isCore: boolean = false): Promise<{ + url: string, + headers: { [key: string]: string } +}> { + const realUrl = getServerRoot(port, isCore) + path; + if (commonStore.platform === 'web') + return { + url: realUrl, + headers: {} + }; + if (!commonStore.proxyPort) + await GetProxyPort().then(p => commonStore.setProxyPort(p)); + return { + url: `http://127.0.0.1:${commonStore.proxyPort}`, + headers: { 'Real-Target': realUrl } + }; +} + export function getServerRoot(defaultLocalPort: number, isCore: boolean = false) { const coreCustomApiUrl = commonStore.settings.coreApiUrl.trim().replace(/\/$/, ''); if (isCore && coreCustomApiUrl) diff --git a/frontend/src/webWails.js b/frontend/src/webWails.js index acf2ce4..c96d37d 100644 --- a/frontend/src/webWails.js +++ b/frontend/src/webWails.js @@ -115,6 +115,12 @@ if (!window.go) { defineApp('ListDirFiles', async () => { return [] }) + defineApp('GetAbsPath', async (path) => { + return path + }) + defineApp('GetProxyPort', async () => { + return 0 + }) defineApp('OpenOpenFileDialog', webOpenOpenFileDialog) defineApp('OpenSaveFileDialog', async (filterPattern, defaultFileName, savedContent) => { const saver = await import('file-saver') diff --git a/frontend/wailsjs/go/backend_golang/App.d.ts b/frontend/wailsjs/go/backend_golang/App.d.ts index 7e88791..a5c8bcd 100644 --- a/frontend/wailsjs/go/backend_golang/App.d.ts +++ b/frontend/wailsjs/go/backend_golang/App.d.ts @@ -32,6 +32,8 @@ export function GetAbsPath(arg1:string):Promise; export function GetPlatform():Promise; +export function GetProxyPort():Promise; + export function GetPyError():Promise; export function InstallPyDep(arg1:string,arg2:boolean):Promise; diff --git a/frontend/wailsjs/go/backend_golang/App.js b/frontend/wailsjs/go/backend_golang/App.js index 9d05405..a480b06 100644 --- a/frontend/wailsjs/go/backend_golang/App.js +++ b/frontend/wailsjs/go/backend_golang/App.js @@ -62,6 +62,10 @@ export function GetPlatform() { return window['go']['backend_golang']['App']['GetPlatform'](); } +export function GetProxyPort() { + return window['go']['backend_golang']['App']['GetProxyPort'](); +} + export function GetPyError() { return window['go']['backend_golang']['App']['GetPyError'](); }