Websocket working again

This commit is contained in:
Florian Hoss 2022-12-18 22:09:01 +01:00
parent 74cd44c66d
commit c85dab3573
13 changed files with 166 additions and 26 deletions

1
go.mod
View file

@ -6,6 +6,7 @@ require (
github.com/caarlos0/env/v6 v6.10.1 github.com/caarlos0/env/v6 v6.10.1
github.com/dariubs/percent v1.0.0 github.com/dariubs/percent v1.0.0
github.com/fsnotify/fsnotify v1.6.0 github.com/fsnotify/fsnotify v1.6.0
github.com/gorilla/websocket v1.5.0
github.com/labstack/echo/v4 v4.9.1 github.com/labstack/echo/v4 v4.9.1
github.com/shirou/gopsutil/v3 v3.22.11 github.com/shirou/gopsutil/v3 v3.22.11
github.com/unjx-de/go-folder v1.0.7 github.com/unjx-de/go-folder v1.0.7

2
go.sum
View file

@ -16,6 +16,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzq
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y= github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y=
github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo= github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=

62
hub/hub.go Normal file
View file

@ -0,0 +1,62 @@
package hub
const (
Weather WsType = iota
System
)
type (
NotifierChan chan Message
WsType uint
Message struct {
WsType WsType `json:"ws_type"`
Message interface{} `json:"message"`
}
Hub struct {
Notifier NotifierChan
NewClients chan NotifierChan
ClosingClients chan NotifierChan
clients map[NotifierChan]struct{}
LiveInformationCh chan Message
}
)
func NewHub() *Hub {
hub := Hub{}
hub.LiveInformationCh = make(chan Message)
hub.Notifier = make(NotifierChan)
hub.NewClients = make(chan NotifierChan)
hub.ClosingClients = make(chan NotifierChan)
hub.clients = make(map[NotifierChan]struct{})
go hub.listen()
go func() {
for {
if msg, ok := <-hub.LiveInformationCh; ok {
hub.Notifier <- msg
}
}
}()
return &hub
}
func (h *Hub) listen() {
for {
select {
case s := <-h.NewClients:
h.clients[s] = struct{}{}
case s := <-h.ClosingClients:
delete(h.clients, s)
case event := <-h.Notifier:
for client := range h.clients {
select {
case client <- event:
default:
close(client)
delete(h.clients, client)
}
}
}
}
}

11
main.go
View file

@ -7,6 +7,7 @@ import (
"github.com/labstack/echo/v4/middleware" "github.com/labstack/echo/v4/middleware"
"go.uber.org/zap" "go.uber.org/zap"
"godash/bookmarks" "godash/bookmarks"
"godash/hub"
"godash/system" "godash/system"
"godash/weather" "godash/weather"
"html/template" "html/template"
@ -17,6 +18,7 @@ import (
type goDash struct { type goDash struct {
router *echo.Echo router *echo.Echo
logger *zap.SugaredLogger logger *zap.SugaredLogger
hub *hub.Hub
config config config config
} }
@ -29,7 +31,7 @@ type config struct {
} }
func main() { func main() {
g := goDash{router: echo.New()} g := goDash{router: echo.New(), hub: hub.NewHub()}
g.router.Renderer = &TemplateRenderer{ g.router.Renderer = &TemplateRenderer{
templates: template.Must(template.ParseGlob("templates/*.gohtml")), templates: template.Must(template.ParseGlob("templates/*.gohtml")),
} }
@ -45,11 +47,11 @@ func main() {
g.router.Use(middleware.GzipWithConfig(middleware.GzipConfig{Level: 5})) g.router.Use(middleware.GzipWithConfig(middleware.GzipConfig{Level: 5}))
g.router.Pre(middleware.RemoveTrailingSlash()) g.router.Pre(middleware.RemoveTrailingSlash())
w := weather.NewWeatherService(g.logger) w := weather.NewWeatherService(g.logger, g.hub)
b := bookmarks.NewBookmarkService(g.logger) b := bookmarks.NewBookmarkService(g.logger)
var s *system.System var s *system.System
if g.config.LiveSystem { if g.config.LiveSystem {
s = system.NewSystemService(g.logger) s = system.NewSystemService(g.logger, g.hub)
} }
g.router.GET("/", func(c echo.Context) error { g.router.GET("/", func(c echo.Context) error {
@ -57,9 +59,10 @@ func main() {
"Title": g.config.Title, "Title": g.config.Title,
"Weather": w.CurrentWeather, "Weather": w.CurrentWeather,
"Bookmarks": b.Categories, "Bookmarks": b.Categories,
"System": s, "System": s.CurrentSystem,
}) })
}) })
g.router.GET("/ws", g.ws)
g.router.Static("/static", "static") g.router.Static("/static", "static")
g.router.Static("/storage/icons", "storage/icons") g.router.Static("/storage/icons", "storage/icons")

56
routes.go Normal file
View file

@ -0,0 +1,56 @@
package main
import (
"errors"
"github.com/gorilla/websocket"
"github.com/labstack/echo/v4"
"godash/hub"
)
var (
upgrader = websocket.Upgrader{}
)
func (g *goDash) ws(c echo.Context) error {
if g.config.PageUrl.String() != c.Request().Header.Get("Origin") {
return errors.New("bad request")
}
ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
if err != nil {
return err
}
messageChan := make(hub.NotifierChan)
g.hub.NewClients <- messageChan
defer func() {
g.hub.ClosingClients <- messageChan
ws.Close()
}()
go func() {
defer ws.Close()
for {
_, _, err := ws.ReadMessage()
if err != nil {
break
}
}
}()
for {
select {
case msg, ok := <-messageChan:
if !ok {
err := ws.WriteMessage(websocket.CloseMessage, []byte{})
if err != nil {
return err
}
return err
}
err := ws.WriteJSON(msg)
if err != nil {
return err
}
}
}
}

View file

@ -24,5 +24,5 @@ func (s *System) liveCpu() {
if err != nil { if err != nil {
return return
} }
s.Live.CPU = math.RoundToEven(p[0]) s.CurrentSystem.Live.CPU = math.RoundToEven(p[0])
} }

View file

@ -24,6 +24,6 @@ func (s *System) liveDisk() {
if err != nil { if err != nil {
return return
} }
s.Live.Disk.Value = readableSize(d.Used) s.CurrentSystem.Live.Disk.Value = readableSize(d.Used)
s.Live.Disk.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(d.Used), float64(d.Total))) s.CurrentSystem.Live.Disk.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(d.Used), float64(d.Total)))
} }

View file

@ -26,6 +26,6 @@ func (s *System) liveRam() {
if err != nil { if err != nil {
return return
} }
s.Live.Ram.Value = readableSize(r.Used) s.CurrentSystem.Live.Ram.Value = readableSize(r.Used)
s.Live.Ram.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(r.Used), float64(r.Total))) s.CurrentSystem.Live.Ram.Percentage = math.RoundToEven(percent.PercentOfFloat(float64(r.Used), float64(r.Total)))
} }

View file

@ -2,11 +2,12 @@ package system
import ( import (
"go.uber.org/zap" "go.uber.org/zap"
"godash/hub"
"time" "time"
) )
func NewSystemService(logging *zap.SugaredLogger) *System { func NewSystemService(logging *zap.SugaredLogger, hub *hub.Hub) *System {
s := System{log: logging} s := System{log: logging, hub: hub}
s.Initialize() s.Initialize()
return &s return &s
} }
@ -17,15 +18,16 @@ func (s *System) UpdateLiveInformation() {
s.liveRam() s.liveRam()
s.liveDisk() s.liveDisk()
s.uptime() s.uptime()
s.hub.LiveInformationCh <- hub.Message{WsType: hub.System, Message: s.CurrentSystem.Live}
time.Sleep(1 * time.Second) time.Sleep(1 * time.Second)
} }
} }
func (s *System) Initialize() { func (s *System) Initialize() {
s.Static.Host = staticHost() s.CurrentSystem.Static.Host = staticHost()
s.Static.CPU = staticCpu() s.CurrentSystem.Static.CPU = staticCpu()
s.Static.Ram = staticRam() s.CurrentSystem.Static.Ram = staticRam()
s.Static.Disk = staticDisk() s.CurrentSystem.Static.Disk = staticDisk()
go s.UpdateLiveInformation() go s.UpdateLiveInformation()
s.log.Debugw("system updated", "cpu", s.Static.CPU.Name, "arch", s.Static.Host.Architecture) s.log.Debugw("system updated", "cpu", s.CurrentSystem.Static.CPU.Name, "arch", s.CurrentSystem.Static.Host.Architecture)
} }

View file

@ -1,9 +1,17 @@
package system package system
import "go.uber.org/zap" import (
"go.uber.org/zap"
"godash/hub"
)
type System struct { type System struct {
hub *hub.Hub
log *zap.SugaredLogger log *zap.SugaredLogger
CurrentSystem CurrentSystem
}
type CurrentSystem struct {
Live LiveInformation `json:"live"` Live LiveInformation `json:"live"`
Static StaticInformation `json:"static"` Static StaticInformation `json:"static"`
} }

View file

@ -9,9 +9,9 @@ func (s *System) uptime() {
if err != nil { if err != nil {
return return
} }
s.Live.Uptime.Days = i.Uptime / 84600 s.CurrentSystem.Live.Uptime.Days = i.Uptime / 84600
s.Live.Uptime.Hours = uint16((i.Uptime % 86400) / 3600) s.CurrentSystem.Live.Uptime.Hours = uint16((i.Uptime % 86400) / 3600)
s.Live.Uptime.Minutes = uint16(((i.Uptime % 86400) % 3600) / 60) s.CurrentSystem.Live.Uptime.Minutes = uint16(((i.Uptime % 86400) % 3600) / 60)
s.Live.Uptime.Seconds = uint16(((i.Uptime % 86400) % 3600) % 60) s.CurrentSystem.Live.Uptime.Seconds = uint16(((i.Uptime % 86400) % 3600) % 60)
s.Live.Uptime.Percentage = float32((s.Live.Uptime.Minutes*100)+s.Live.Uptime.Seconds) / 60 s.CurrentSystem.Live.Uptime.Percentage = float32((s.CurrentSystem.Live.Uptime.Minutes*100)+s.CurrentSystem.Live.Uptime.Seconds) / 60
} }

View file

@ -1,9 +1,13 @@
package weather package weather
import "go.uber.org/zap" import (
"go.uber.org/zap"
"godash/hub"
)
type weather struct { type weather struct {
CurrentWeather OpenWeather CurrentWeather OpenWeather
hub *hub.Hub
config config config config
log *zap.SugaredLogger log *zap.SugaredLogger
} }

View file

@ -5,14 +5,15 @@ import (
"fmt" "fmt"
"github.com/caarlos0/env/v6" "github.com/caarlos0/env/v6"
"go.uber.org/zap" "go.uber.org/zap"
"godash/hub"
"io" "io"
"math" "math"
"net/http" "net/http"
"time" "time"
) )
func NewWeatherService(logging *zap.SugaredLogger) *weather { func NewWeatherService(logging *zap.SugaredLogger, hub *hub.Hub) *weather {
var w = weather{log: logging} var w = weather{log: logging, hub: hub}
if err := env.Parse(&w.config); err != nil { if err := env.Parse(&w.config); err != nil {
panic(err) panic(err)
} }
@ -67,6 +68,7 @@ func (w *weather) updateWeather(interval time.Duration) {
w.log.Debugw("weather updated", "temp", w.CurrentWeather.Temp) w.log.Debugw("weather updated", "temp", w.CurrentWeather.Temp)
} }
resp.Body.Close() resp.Body.Close()
w.hub.LiveInformationCh <- hub.Message{WsType: hub.Weather, Message: w.CurrentWeather}
} }
time.Sleep(interval) time.Sleep(interval)
} }