package server import ( "fmt" "log" "net/http" "strings" "git.neurocipta.com/rogerferdinan/safe-web-socket/internal" "github.com/gorilla/websocket" ) type SafeWebsocketServerBuilder struct { baseHost *string `nil_checker:"required"` basePort *uint16 `nil_checker:"required"` upgrader *websocket.Upgrader `nil_checker:"required"` mux *http.ServeMux `nil_checker:"required"` } func NewSafeWebsocketServerBuilder() *SafeWebsocketServerBuilder { h := internal.NewHub() h.Run() return &SafeWebsocketServerBuilder{ upgrader: &websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool { return true }, }, mux: http.NewServeMux(), } } func (b *SafeWebsocketServerBuilder) BaseHost(baseHost string) *SafeWebsocketServerBuilder { b.baseHost = &baseHost return b } func (b *SafeWebsocketServerBuilder) BasePort(basePort uint16) *SafeWebsocketServerBuilder { b.basePort = &basePort return b } func (b *SafeWebsocketServerBuilder) HandleFunc( pattern string, fn func(http.ResponseWriter, *http.Request), ) *SafeWebsocketServerBuilder { b.mux.HandleFunc(pattern, fn) return b } func (b *SafeWebsocketServerBuilder) HandleFuncWebsocket( pattern string, subscribedPath string, writeFunc func(chan []byte), ) *SafeWebsocketServerBuilder { h := internal.NewHub() h.Run() b.mux.HandleFunc(pattern+subscribedPath, func(w http.ResponseWriter, r *http.Request) { conn, err := b.upgrader.Upgrade(w, r, nil) if err != nil { http.Error(w, "upgrade failed", http.StatusBadRequest) return } subscribedPath := strings.TrimPrefix(r.URL.Path, pattern) fmt.Println(subscribedPath) if subscribedPath == "" { http.Error(w, "invalid path", http.StatusBadRequest) return } c := internal.NewClient(conn, subscribedPath) h.Register <- c internal.WritePump(c, h) internal.ReadPump(c) writeFunc(h.Broadcast) }) return b } func (b *SafeWebsocketServerBuilder) Build() (*SafeWebsocketServer, error) { if err := internal.NilChecker(b); err != nil { return nil, err } safeServer := SafeWebsocketServer{ url: fmt.Sprintf("%s:%d", *b.baseHost, *b.basePort), mux: b.mux, mu: internal.NewCustomRwMutex(), } return &safeServer, nil } type SafeWebsocketServer struct { hub *internal.Hub mux *http.ServeMux url string mu *internal.CustomRwMutex } func (s *SafeWebsocketServer) ListenAndServe() error { log.Printf("HTTP serve on %s\n", s.url) if err := http.ListenAndServe(s.url, s.mux); err != nil { return fmt.Errorf("failed to serve websocket: %w", err) } return nil }