6
0
mirror of https://git.mills.io/prologic/msgbus.git synced 2024-07-01 03:01:50 +00:00
prologic-msgbus/server.go
2017-06-03 20:16:35 +01:00

109 lines
2.1 KiB
Go

package msgbus
import (
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"golang.org/x/net/websocket"
"github.com/julienschmidt/httprouter"
)
// IndexHandler ...
func IndexHandler(w http.ResponseWriter, r *http.Request, _ httprouter.Params) {
fmt.Fprint(w, "Welcome!\n")
}
// PushHandler ...
func PushHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
topic := p.ByName("topic")
websocket.Handler(PushWebSocketHandler(topic)).ServeHTTP(w, r)
}
// PullHandler ...
func PullHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
topic := p.ByName("topic")
message, ok := mb.Get(topic)
if !ok {
http.Error(w, "Not Found", http.StatusNotFound)
return
}
out, err := json.Marshal(message)
if err != nil {
http.Error(w, "Internal Error", http.StatusInternalServerError)
return
}
w.Write(out)
}
// PutHandler ...
func PutHandler(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
topic := p.ByName("topic")
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Internal Error", http.StatusInternalServerError)
return
}
mb.Put(topic, mb.NewMessage(body))
}
// PushWebSocketHandler ...
func PushWebSocketHandler(topic string) websocket.Handler {
return func(conn *websocket.Conn) {
id := conn.Request().RemoteAddr
ch := mb.Subscribe(id, topic)
defer func() {
mb.Unsubscribe(id, topic)
}()
var (
err error
ack msgbus.Ack
)
for {
msg := <-ch
err = websocket.JSON.Send(conn, msg)
if err != nil {
log.Printf("Error sending msg to %s", id)
continue
}
err = websocket.JSON.Receive(conn, &ack)
if err != nil {
log.Printf("Error receiving ack from %s", id)
continue
}
log.Printf("message %v acked %v by %s", msg, ack, id)
}
}
}
type Server struct {
bus *msgbus.MsgBus
router *httprouter.Router
}
func (s *Server) init() {
s.bus = msgbus.NewMessageBus()
s.router = httprouter.New()
router.GET("/", IndexHandler)
router.GET("/push/:topic", PushHandler)
router.GET("/pull/:topic", PullHandler)
router.PUT("/:topic", PutHandler)
}
func (s *Server) Run() {
s.init()
log.Fatal(http.ListenAndServe(s.bind, s.router))
}