dashboard.go 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package dashboard
  2. import (
  3. "html/template"
  4. "math/rand"
  5. "net/http"
  6. "time"
  7. _ "github.com/flashmob/go-guerrilla/dashboard/statik"
  8. "github.com/gorilla/mux"
  9. "github.com/gorilla/websocket"
  10. )
  11. const (
  12. dashboard = "index.html"
  13. dashboardPath = "dashboard/html/index.html"
  14. sessionTimeout = time.Hour * 24 // TODO replace with config
  15. )
  16. var (
  17. // Cache of HTML templates
  18. templates = template.Must(template.ParseFiles(dashboardPath))
  19. config *Config
  20. sessions map[string]*session
  21. )
  22. var upgrader = websocket.Upgrader{
  23. ReadBufferSize: 1024,
  24. WriteBufferSize: 1024,
  25. // TODO below for testing w/ webpack only, change before merging
  26. CheckOrigin: func(r *http.Request) bool { return true },
  27. }
  28. type Config struct {
  29. ListenInterface string
  30. }
  31. func Run(c *Config) {
  32. // TODO below for testing w/ webpack only, change before merging
  33. // statikFS, _ := fs.New()
  34. config = c
  35. sessions = map[string]*session{}
  36. r := mux.NewRouter()
  37. r.HandleFunc("/ws", webSocketHandler)
  38. // TODO below for testing w/ webpack only, change before merging
  39. r.PathPrefix("/").Handler(http.FileServer(http.Dir("dashboard/js/build")))
  40. rand.Seed(time.Now().UnixNano())
  41. go dataListener(tickInterval)
  42. http.ListenAndServe(c.ListenInterface, r)
  43. }
  44. func indexHandler(w http.ResponseWriter, r *http.Request) {
  45. c, err := r.Cookie("SID")
  46. _, sidExists := sessions[c.Value]
  47. if err != nil || !sidExists {
  48. // No SID cookie
  49. startSession(w, r)
  50. }
  51. w.WriteHeader(http.StatusOK)
  52. templates.ExecuteTemplate(w, dashboard, nil)
  53. }
  54. func webSocketHandler(w http.ResponseWriter, r *http.Request) {
  55. cookie, err := r.Cookie("SID")
  56. if err != nil {
  57. // TODO error
  58. w.WriteHeader(http.StatusInternalServerError)
  59. }
  60. sess, sidExists := sessions[cookie.Value]
  61. if !sidExists {
  62. // No SID cookie
  63. sess = startSession(w, r)
  64. }
  65. conn, err := upgrader.Upgrade(w, r, nil)
  66. if err != nil {
  67. w.WriteHeader(http.StatusInternalServerError)
  68. // TODO Internal error
  69. return
  70. }
  71. sess.ws = conn
  72. c := make(chan *message)
  73. sess.send = c
  74. // TODO send store contents at connection time
  75. store.subscribe(sess.id, c)
  76. go sess.receive()
  77. go sess.transmit()
  78. go store.initSession(sess)
  79. }
  80. func startSession(w http.ResponseWriter, r *http.Request) *session {
  81. sessionID := newSessionID()
  82. cookie := &http.Cookie{
  83. Name: "SID",
  84. Value: sessionID,
  85. Path: "/",
  86. // Secure: true, // TODO re-add this when TLS is set up
  87. }
  88. sess := &session{
  89. id: sessionID,
  90. }
  91. http.SetCookie(w, cookie)
  92. sessions[sessionID] = sess
  93. return sess
  94. }
  95. func getSession(r *http.Request) *session {
  96. c, err := r.Cookie("SID")
  97. if err != nil {
  98. return nil
  99. }
  100. sid := c.Value
  101. sess, ok := sessions[sid]
  102. if !ok {
  103. return nil
  104. }
  105. return sess
  106. }