1
0
mirror of https://github.com/jhillyerd/inbucket.git synced 2025-12-17 17:47:03 +00:00

Create V2 API for monitor+deletes, revert V1 API (#347)

* Revert socketv1 controller API to maintain V1 contract, introduce
V2 controller for Inbucket UI.

Signed-off-by: James Hillyerd <james@hillyerd.com>

* Introduce MessageID for deletes, instead of recycling header

Signed-off-by: James Hillyerd <james@hillyerd.com>

* Update UI for monitor V2 API

Signed-off-by: James Hillyerd <james@hillyerd.com>

---------

Signed-off-by: James Hillyerd <james@hillyerd.com>
This commit is contained in:
James Hillyerd
2023-02-17 12:37:17 -08:00
committed by GitHub
parent b554c7db83
commit 82ddf2141c
7 changed files with 283 additions and 64 deletions

View File

@@ -15,37 +15,37 @@ import (
const (
// Time allowed to write a message to the peer.
writeWait = 10 * time.Second
writeWaitV1 = 10 * time.Second
// Send pings to peer with this period. Must be less than pongWait.
pingPeriod = (pongWait * 9) / 10
pingPeriodV1 = (pongWaitV1 * 9) / 10
// Time allowed to read the next pong message from the peer.
pongWait = 60 * time.Second
pongWaitV1 = 60 * time.Second
// Maximum message size allowed from peer.
maxMessageSize = 512
maxMessageSizeV1 = 512
)
// options for gorilla connection upgrader
var upgrader = websocket.Upgrader{
var upgraderV1 = websocket.Upgrader{
ReadBufferSize: 1024,
WriteBufferSize: 1024,
}
// msgListener handles messages from the msghub
type msgListener struct {
hub *msghub.Hub // Global message hub.
c chan *model.JSONMonitorEventV1 // Queue of incoming events.
mailbox string // Name of mailbox to monitor, "" == all mailboxes.
// msgListenerV1 handles messages from the msghub
type msgListenerV1 struct {
hub *msghub.Hub // Global message hub
c chan event.MessageMetadata // Queue of messages from Receive()
mailbox string // Name of mailbox to monitor, "" == all mailboxes
}
// newMsgListener creates a listener and registers it. Optional mailbox parameter will restrict
// newMsgListenerV1 creates a listener and registers it. Optional mailbox parameter will restrict
// messages sent to WebSocket to that mailbox only.
func newMsgListener(hub *msghub.Hub, mailbox string) *msgListener {
ml := &msgListener{
func newMsgListenerV1(hub *msghub.Hub, mailbox string) *msgListenerV1 {
ml := &msgListenerV1{
hub: hub,
c: make(chan *model.JSONMonitorEventV1, 100),
c: make(chan event.MessageMetadata, 100),
mailbox: mailbox,
}
hub.AddListener(ml)
@@ -53,50 +53,31 @@ func newMsgListener(hub *msghub.Hub, mailbox string) *msgListener {
}
// Receive handles an incoming message.
func (ml *msgListener) Receive(msg event.MessageMetadata) error {
func (ml *msgListenerV1) Receive(msg event.MessageMetadata) error {
if ml.mailbox != "" && ml.mailbox != msg.Mailbox {
// Did not match the watched mailbox name.
return nil
}
// Enqueue for websocket.
ml.c <- &model.JSONMonitorEventV1{
Variant: "message-stored",
Header: metadataToHeader(&msg),
}
ml.c <- msg
return nil
}
// Delete handles a deleted message.
func (ml *msgListener) Delete(mailbox string, id string) error {
if ml.mailbox != "" && ml.mailbox != mailbox {
// Did not match watched mailbox name.
return nil
}
// Enqueue for websocket.
ml.c <- &model.JSONMonitorEventV1{
Variant: "message-deleted",
Header: &model.JSONMessageHeaderV1{
Mailbox: mailbox,
ID: id,
},
}
func (ml *msgListenerV1) Delete(mailbox string, id string) error {
// Deletes are ignored in socketv1 API.
return nil
}
// WSReader makes sure the websocket client is still connected, discards any messages from client
func (ml *msgListener) WSReader(conn *websocket.Conn) {
func (ml *msgListenerV1) WSReader(conn *websocket.Conn) {
slog := log.With().Str("module", "rest").Str("proto", "WebSocket").
Str("remote", conn.RemoteAddr().String()).Logger()
defer ml.Close()
conn.SetReadLimit(maxMessageSize)
conn.SetReadDeadline(time.Now().Add(pongWait))
conn.SetReadLimit(maxMessageSizeV1)
conn.SetReadDeadline(time.Now().Add(pongWaitV1))
conn.SetPongHandler(func(string) error {
slog.Debug().Msg("Got pong")
conn.SetReadDeadline(time.Now().Add(pongWait))
conn.SetReadDeadline(time.Now().Add(pongWaitV1))
return nil
})
@@ -119,8 +100,8 @@ func (ml *msgListener) WSReader(conn *websocket.Conn) {
}
// WSWriter makes sure the websocket client is still connected
func (ml *msgListener) WSWriter(conn *websocket.Conn) {
ticker := time.NewTicker(pingPeriod)
func (ml *msgListenerV1) WSWriter(conn *websocket.Conn) {
ticker := time.NewTicker(pingPeriodV1)
defer func() {
ticker.Stop()
ml.Close()
@@ -129,20 +110,20 @@ func (ml *msgListener) WSWriter(conn *websocket.Conn) {
// Handle messages from hub until msgListener is closed
for {
select {
case event, ok := <-ml.c:
conn.SetWriteDeadline(time.Now().Add(writeWait))
case msg, ok := <-ml.c:
conn.SetWriteDeadline(time.Now().Add(writeWaitV1))
if !ok {
// msgListener closed, exit
conn.WriteMessage(websocket.CloseMessage, []byte{})
return
}
if conn.WriteJSON(event) != nil {
if conn.WriteJSON(metadataToHeader(&msg)) != nil {
// Write failed
return
}
case <-ticker.C:
// Send ping
conn.SetWriteDeadline(time.Now().Add(writeWait))
conn.SetWriteDeadline(time.Now().Add(writeWaitV1))
if conn.WriteMessage(websocket.PingMessage, []byte{}) != nil {
// Write error
return
@@ -154,7 +135,7 @@ func (ml *msgListener) WSWriter(conn *websocket.Conn) {
}
// Close removes the listener registration
func (ml *msgListener) Close() {
func (ml *msgListenerV1) Close() {
select {
case <-ml.c:
// Already closed
@@ -169,7 +150,7 @@ func (ml *msgListener) Close() {
func MonitorAllMessagesV1(
w http.ResponseWriter, req *http.Request, ctx *web.Context) (err error) {
// Upgrade to Websocket.
conn, err := upgrader.Upgrade(w, req, nil)
conn, err := upgraderV1.Upgrade(w, req, nil)
if err != nil {
return err
}
@@ -181,7 +162,7 @@ func MonitorAllMessagesV1(
log.Debug().Str("module", "rest").Str("proto", "WebSocket").
Str("remote", conn.RemoteAddr().String()).Msg("Upgraded to WebSocket")
// Create, register listener; then interact with conn.
ml := newMsgListener(ctx.MsgHub, "")
ml := newMsgListenerV1(ctx.MsgHub, "")
go ml.WSWriter(conn)
ml.WSReader(conn)
return nil
@@ -196,7 +177,7 @@ func MonitorMailboxMessagesV1(
return err
}
// Upgrade to Websocket.
conn, err := upgrader.Upgrade(w, req, nil)
conn, err := upgraderV1.Upgrade(w, req, nil)
if err != nil {
return err
}
@@ -208,7 +189,7 @@ func MonitorMailboxMessagesV1(
log.Debug().Str("module", "rest").Str("proto", "WebSocket").
Str("remote", conn.RemoteAddr().String()).Msg("Upgraded to WebSocket")
// Create, register listener; then interact with conn.
ml := newMsgListener(ctx.MsgHub, name)
ml := newMsgListenerV1(ctx.MsgHub, name)
go ml.WSWriter(conn)
ml.WSReader(conn)
return nil