refactor hub dev server

- moved html replacement functionality from vite to go
This commit is contained in:
henrygd
2025-09-01 22:16:57 -04:00
parent fadfc5d81d
commit 86e87f0d47
4 changed files with 62 additions and 12 deletions

View File

@@ -112,6 +112,8 @@ func (h *Hub) initialize(e *core.ServeEvent) error {
// set URL if BASE_URL env is set // set URL if BASE_URL env is set
if h.appURL != "" { if h.appURL != "" {
settings.Meta.AppURL = h.appURL settings.Meta.AppURL = h.appURL
} else {
h.appURL = settings.Meta.AppURL
} }
if err := e.App.Save(settings); err != nil { if err := e.App.Save(settings); err != nil {
return err return err

View File

@@ -3,18 +3,74 @@
package hub package hub
import ( import (
"beszel"
"fmt"
"io"
"log/slog"
"net/http"
"net/http/httputil" "net/http/httputil"
"net/url" "net/url"
"strings"
"github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/core"
) )
// Wraps http.RoundTripper to modify dev proxy HTML responses
type responseModifier struct {
transport http.RoundTripper
hub *Hub
}
func (rm *responseModifier) RoundTrip(req *http.Request) (*http.Response, error) {
resp, err := rm.transport.RoundTrip(req)
if err != nil {
return resp, err
}
// Only modify HTML responses
contentType := resp.Header.Get("Content-Type")
if !strings.Contains(contentType, "text/html") {
return resp, nil
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return resp, err
}
resp.Body.Close()
// Create a new response with the modified body
modifiedBody := rm.modifyHTML(string(body))
resp.Body = io.NopCloser(strings.NewReader(modifiedBody))
resp.ContentLength = int64(len(modifiedBody))
resp.Header.Set("Content-Length", fmt.Sprintf("%d", len(modifiedBody)))
return resp, nil
}
func (rm *responseModifier) modifyHTML(html string) string {
parsedURL, err := url.Parse(rm.hub.appURL)
if err != nil {
return html
}
// fix base paths in html if using subpath
basePath := strings.TrimSuffix(parsedURL.Path, "/") + "/"
html = strings.ReplaceAll(html, "./", basePath)
html = strings.Replace(html, "{{V}}", beszel.Version, 1)
html = strings.Replace(html, "{{HUB_URL}}", rm.hub.appURL, 1)
return html
}
// startServer sets up the development server for Beszel // startServer sets up the development server for Beszel
func (h *Hub) startServer(se *core.ServeEvent) error { func (h *Hub) startServer(se *core.ServeEvent) error {
slog.Info("starting server", "appURL", h.appURL)
proxy := httputil.NewSingleHostReverseProxy(&url.URL{ proxy := httputil.NewSingleHostReverseProxy(&url.URL{
Scheme: "http", Scheme: "http",
Host: "localhost:5173", Host: "localhost:5173",
}) })
proxy.Transport = &responseModifier{
transport: http.DefaultTransport,
hub: h,
}
se.Router.GET("/{path...}", func(e *core.RequestEvent) error { se.Router.GET("/{path...}", func(e *core.RequestEvent) error {
proxy.ServeHTTP(e.Response, e.Request) proxy.ServeHTTP(e.Response, e.Request)
return nil return nil

View File

@@ -24,9 +24,9 @@ func (h *Hub) startServer(se *core.ServeEvent) error {
// fix base paths in html if using subpath // fix base paths in html if using subpath
basePath := strings.TrimSuffix(parsedURL.Path, "/") + "/" basePath := strings.TrimSuffix(parsedURL.Path, "/") + "/"
indexFile, _ := fs.ReadFile(site.DistDirFS, "index.html") indexFile, _ := fs.ReadFile(site.DistDirFS, "index.html")
indexContent := strings.ReplaceAll(string(indexFile), "./", basePath) html := strings.ReplaceAll(string(indexFile), "./", basePath)
indexContent = strings.Replace(indexContent, "{{V}}", beszel.Version, 1) html = strings.Replace(html, "{{V}}", beszel.Version, 1)
indexContent = strings.Replace(indexContent, "{{HUB_URL}}", h.appURL, 1) html = strings.Replace(html, "{{HUB_URL}}", h.appURL, 1)
// set up static asset serving // set up static asset serving
staticPaths := [2]string{"/static/", "/assets/"} staticPaths := [2]string{"/static/", "/assets/"}
serveStatic := apis.Static(site.DistDirFS, false) serveStatic := apis.Static(site.DistDirFS, false)
@@ -45,7 +45,7 @@ func (h *Hub) startServer(se *core.ServeEvent) error {
e.Response.Header().Del("X-Frame-Options") e.Response.Header().Del("X-Frame-Options")
e.Response.Header().Set("Content-Security-Policy", csp) e.Response.Header().Set("Content-Security-Policy", csp)
} }
return e.HTML(http.StatusOK, indexContent) return e.HTML(http.StatusOK, html)
}) })
return nil return nil
} }

View File

@@ -3,7 +3,6 @@ import path from "path"
import tailwindcss from "@tailwindcss/vite" import tailwindcss from "@tailwindcss/vite"
import react from "@vitejs/plugin-react-swc" import react from "@vitejs/plugin-react-swc"
import { lingui } from "@lingui/vite-plugin" import { lingui } from "@lingui/vite-plugin"
import { version } from "./package.json"
export default defineConfig({ export default defineConfig({
base: "./", base: "./",
@@ -13,13 +12,6 @@ export default defineConfig({
}), }),
lingui(), lingui(),
tailwindcss(), tailwindcss(),
{
name: "replace version in index.html during dev",
apply: "serve",
transformIndexHtml(html) {
return html.replace("{{V}}", version).replace("{{HUB_URL}}", "")
},
},
], ],
esbuild: { esbuild: {
legalComments: "external", legalComments: "external",