package dashboard import ( "html/template" "math/rand" "net/http" "time" _ "github.com/flashmob/go-guerrilla/dashboard/statik" "github.com/gorilla/mux" "github.com/gorilla/websocket" ) const ( dashboard = "index.html" dashboardPath = "dashboard/html/index.html" sessionTimeout = time.Hour * 24 // TODO replace with config ) var ( // Cache of HTML templates templates = template.Must(template.ParseFiles(dashboardPath)) config *Config sessions map[string]*session ) var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, // TODO below for testing w/ webpack only, change before merging CheckOrigin: func(r *http.Request) bool { return true }, } type Config struct { ListenInterface string } func Run(c *Config) { // TODO below for testing w/ webpack only, change before merging // statikFS, _ := fs.New() config = c sessions = map[string]*session{} r := mux.NewRouter() r.HandleFunc("/ws", webSocketHandler) // TODO below for testing w/ webpack only, change before merging r.PathPrefix("/").Handler(http.FileServer(http.Dir("dashboard/js/build"))) rand.Seed(time.Now().UnixNano()) go dataListener(tickInterval) http.ListenAndServe(c.ListenInterface, r) } func indexHandler(w http.ResponseWriter, r *http.Request) { c, err := r.Cookie("SID") _, sidExists := sessions[c.Value] if err != nil || !sidExists { // No SID cookie startSession(w, r) } w.WriteHeader(http.StatusOK) templates.ExecuteTemplate(w, dashboard, nil) } func webSocketHandler(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie("SID") if err != nil { // TODO error w.WriteHeader(http.StatusInternalServerError) } sess, sidExists := sessions[cookie.Value] if !sidExists { // No SID cookie sess = startSession(w, r) } conn, err := upgrader.Upgrade(w, r, nil) if err != nil { w.WriteHeader(http.StatusInternalServerError) // TODO Internal error return } sess.ws = conn c := make(chan *message) sess.send = c // TODO send store contents at connection time store.subscribe(sess.id, c) go sess.receive() go sess.transmit() go store.initSession(sess) } func startSession(w http.ResponseWriter, r *http.Request) *session { sessionID := newSessionID() cookie := &http.Cookie{ Name: "SID", Value: sessionID, Path: "/", // Secure: true, // TODO re-add this when TLS is set up } sess := &session{ id: sessionID, } http.SetCookie(w, cookie) sessions[sessionID] = sess return sess } func getSession(r *http.Request) *session { c, err := r.Cookie("SID") if err != nil { return nil } sid := c.Value sess, ok := sessions[sid] if !ok { return nil } return sess }