package server import ( "context" "fmt" "html/template" "net/http" "time" "go.uber.org/zap" ) type WebServer struct { Logger *zap.SugaredLogger ListenAddr string ctx context.Context rtmpServer *RTMPServer httpServer *http.Server } func NewWebServer(ctx context.Context, rs *RTMPServer) *WebServer { return &WebServer{ ctx: ctx, rtmpServer: rs, Logger: zap.NewNop().Sugar(), ListenAddr: ":8077", } } func (ws *WebServer) Serve() error { ws.httpServer = &http.Server{ Addr: ws.ListenAddr, Handler: http.HandlerFunc(ws.IndexHandler), } go func() { <-ws.ctx.Done() ws.Logger.Debugw("HTTP shutdown signal received.") shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() _ = ws.httpServer.Shutdown(shutdownCtx) }() err := ws.httpServer.ListenAndServe() if err != nil && err != http.ErrServerClosed { ws.Logger.Warnw("HTTP Server stopped with error.", "error", err) return err } ws.Logger.Info("HTTP server stopped.") return nil } func (ws *WebServer) IndexHandler(w http.ResponseWriter, r *http.Request) { data := struct { Streams []struct { Name string URL template.URL } }{} for _, s := range ws.rtmpServer.streams { stream := struct { Name string URL template.URL }{ Name: s.Name, URL: template.URL(fmt.Sprintf("rtmp://localhost:5566/view/%s", s.Name)), } data.Streams = append(data.Streams, stream) } tmpl := template.Must(template.ParseFiles("server/templates/index.html")) w.Header().Add("Content-Type", "text/html") tmpl.Execute(w, data) }