Feature(Go): Web auth, WebSocket signaling and live device list (Phase 3)

This commit is contained in:
yuanyuanxiang
2026-05-17 22:18:29 +02:00
committed by yuanyuanxiang
parent 534d3650c4
commit 4ea6ed252c
13 changed files with 1211 additions and 21 deletions

View File

@@ -2,6 +2,7 @@ package web
import (
"context"
"encoding/json"
"errors"
"fmt"
"net"
@@ -9,21 +10,28 @@ import (
"strconv"
"time"
"github.com/yuanyuanxiang/SimpleRemoter/server/go/hub"
"github.com/yuanyuanxiang/SimpleRemoter/server/go/logger"
"github.com/yuanyuanxiang/SimpleRemoter/server/go/wsauth"
)
// Server serves the web remote desktop UI: the embedded index.html, xterm.js
// static assets, and the PWA manifest. WebSocket signaling, device list and
// screen streaming will be wired up in later phases.
// static assets, the PWA manifest, and JSON APIs backed by the device hub.
// WebSocket signaling and screen streaming will be wired up in later phases.
type Server struct {
port int
log *logger.Logger
srv *http.Server
hub *hub.Hub
auth *wsauth.Authenticator
ws *wsHub
}
// New creates an HTTP server bound to the given port. port=0 disables the server.
func New(port int, log *logger.Logger) *Server {
return &Server{port: port, log: log}
// The hub provides read access to the online-device registry; the authenticator
// owns user accounts and session tokens.
func New(port int, log *logger.Logger, h *hub.Hub, auth *wsauth.Authenticator) *Server {
return &Server{port: port, log: log, hub: h, auth: auth}
}
// Start launches the server in a goroutine and returns immediately.
@@ -34,10 +42,14 @@ func (s *Server) Start() error {
return nil
}
s.ws = newWSHub(s.auth, s.hub, s.log)
mux := http.NewServeMux()
mux.HandleFunc("/", s.handleIndex)
mux.HandleFunc("/health", s.handleHealth)
mux.HandleFunc("/manifest.json", s.handleManifest)
mux.HandleFunc("/api/devices", s.handleDevices)
mux.HandleFunc("/ws", s.ws.serve)
mux.HandleFunc("/static/xterm.js", staticHandler(xtermJS, "application/javascript; charset=utf-8"))
mux.HandleFunc("/static/xterm.css", staticHandler(xtermCSS, "text/css; charset=utf-8"))
mux.HandleFunc("/static/xterm-fit.js", staticHandler(xtermFitJS, "application/javascript; charset=utf-8"))
@@ -66,6 +78,9 @@ func (s *Server) Start() error {
// Stop gracefully shuts the server down.
func (s *Server) Stop() {
if s.ws != nil {
s.ws.stop()
}
if s.srv == nil {
return
}
@@ -89,6 +104,18 @@ func (s *Server) handleHealth(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte(`{"status":"ok"}`))
}
// handleDevices returns a JSON snapshot of currently-online devices. Empty
// array (not null) when no clients are connected — matches what the front-end
// will eventually expect.
func (s *Server) handleDevices(w http.ResponseWriter, r *http.Request) {
devices := s.hub.ListDevices()
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("Cache-Control", "no-store")
if err := json.NewEncoder(w).Encode(devices); err != nil {
s.log.Error("encode /api/devices: %v", err)
}
}
// PWA manifest. Referenced by <link rel="manifest"> in index.html.
// Static JSON, no template needed.
const manifestJSON = `{