// tera-web serves static browser assets and the same-origin REST/stream proxy. package main import ( "context" "log" "net/http" "os" "os/signal" "strings" "syscall" "time" "tera-clone/services/tera-api/internal/webgateway" ) func main() { listenAddress := webGetenv("TERA_WEB_LISTEN_ADDR", "127.0.0.1:8080") handler, err := webgateway.NewHandler(webgateway.Options{ StaticRoot: webGetenv("TERA_WEB_STATIC_ROOT", "../../webapp"), APIUpstream: webGetenv("TERA_WEB_API_UPSTREAM", "http://127.0.0.1:8082"), SessionUpstream: webGetenv("TERA_WEB_SESSION_UPSTREAM", "http://127.0.0.1:8081"), }) if err != nil { log.Fatalf("tera-web setup failed: %v", err) } server := &http.Server{ Addr: listenAddress, Handler: handler, ReadHeaderTimeout: 5 * time.Second, IdleTimeout: 60 * time.Second, } log.Printf("tera-web listening on http://%s", listenAddress) serverErrors := make(chan error, 1) go func() { serverErrors <- server.ListenAndServe() }() signalContext, stopSignals := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM) defer stopSignals() select { case <-signalContext.Done(): shutdownContext, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() if err := server.Shutdown(shutdownContext); err != nil { log.Printf("tera-web HTTP shutdown failed: %v", err) } case err := <-serverErrors: if err != nil && err != http.ErrServerClosed { log.Fatalf("tera-web failed: %v", err) } } } func webGetenv(key, fallback string) string { if value := strings.TrimSpace(os.Getenv(key)); value != "" { return value } return fallback }