package main import ( "log" "net/http" "strconv" "time" "git.lattuga.net/boyska/circolog" "github.com/gorilla/websocket" "gopkg.in/mcuadros/go-syslog.v2/format" ) func setupHTTP(hub circolog.Hub) { http.HandleFunc("/", getHTTPHandler(hub)) http.HandleFunc("/ws", getWSHandler(hub)) } func getHTTPHandler(hub circolog.Hub) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { client := circolog.Client{ Messages: make(chan format.LogParts, 20), Nofollow: true} hub.Register <- client err := r.ParseForm() if err != nil { log.Println("error parsing http request", err) } // Looking for known parameter in the request // TODO: write specialized function var requestMessageLen int if reqL, ok := r.Form["l"]; ok { if len(reqL) == 1 { requestMessageLen, err = strconv.Atoi(reqL[0]) if err != nil || requestMessageLen <= 0 { log.Println("malformed request on parameter l") requestMessageLen = -1 w.WriteHeader(400) } } else { log.Println("malformed request on parameter l") requestMessageLen = -1 w.WriteHeader(400) } } if requestMessageLen >= 0 { i := 1 for x := range client.Messages { w.Write([]byte(circolog.FormatSyslog(x))) w.Write([]byte("\n")) if requestMessageLen != 0 && i >= requestMessageLen { break } i++ } } } } func getWSHandler(hub circolog.Hub) http.HandlerFunc { var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, } return func(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { return } client := circolog.Client{Messages: make(chan format.LogParts, 20)} hub.Register <- client // Allow collection of memory referenced by the caller by doing all work in // new goroutines. go func(conn *websocket.Conn, c circolog.Client) { defer func() { hub.Unregister <- c conn.Close() }() for { select { case message, ok := <-c.Messages: conn.SetWriteDeadline(time.Now().Add(10 * time.Second)) if !ok { // The hub closed the channel. conn.WriteMessage(websocket.CloseMessage, []byte{}) return } w, err := conn.NextWriter(websocket.TextMessage) if err != nil { return } w.Write([]byte(circolog.FormatSyslog(message))) if err := w.Close(); err != nil { return } // TODO: ticker/ping } } }(conn, client) } }