Skip to content

Instantly share code, notes, and snippets.

@lnsp
Created January 2, 2020 19:10
Show Gist options
  • Save lnsp/cc68d381fa7f412397cd9fbc6eca9376 to your computer and use it in GitHub Desktop.
Save lnsp/cc68d381fa7f412397cd9fbc6eca9376 to your computer and use it in GitHub Desktop.
Simple HTTP stream messaging server
package main
import (
"fmt"
"io/ioutil"
"net/http"
"os"
"strings"
"sync"
)
type Channel struct {
sync.Mutex
Refcount int64
Msgbuf chan []byte
}
func main() {
var mu sync.Mutex
channels := make(map[string]*Channel)
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
channel := strings.TrimPrefix(r.URL.Path, "/")
if r.Method != http.MethodGet && r.Method != http.MethodPost {
http.Error(w, "method not allowed", http.StatusMethodNotAllowed)
return
}
mu.Lock()
ch, ok := channels[channel]
if !ok {
ch := &Channel{Msgbuf: make(chan []byte)}
channels[channel] = ch
}
mu.Unlock()
ch.Lock()
ch.Refcount++
ch.Unlock()
switch r.Method {
case http.MethodGet:
msg := <-ch.Msgbuf
w.Write(msg)
case http.MethodPost:
msg, _ := ioutil.ReadAll(r.Body)
ch.Msgbuf <- msg
}
ch.Lock()
ch.Refcount--
if ch.Refcount <= 0 {
mu.Lock()
delete(channels, channel)
mu.Unlock()
}
ch.Unlock()
})
addr := os.Getenv("HTTQ_ADDR")
if err := http.ListenAndServe(addr, nil); err != nil {
fmt.Fprintf(os.Stderr, "listen: %v\n", err)
os.Exit(1)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment