/
responder.go
62 lines (48 loc) · 1.39 KB
/
responder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
package server
import (
"net/http"
"time"
"github.com/gorilla/websocket"
"github.com/labstack/echo/v4"
)
// wsCloseTimeout is the timeout of a WebSocket close message.
const wsCloseTimeout = 3 * time.Second
// errorMap maps error object to HTTP status code.
var errorMap = map[error]int{}
// Upgrader is the websocket upgrader.
var upgrader = websocket.Upgrader{}
// Error responds to client with an error. The error is logged and translated
// to proper HTTP status response.
func Error(c echo.Context, err error) error {
c.Logger().Error(err)
status, ok := errorMap[err]
if !ok {
status = http.StatusInternalServerError
}
return c.JSON(status, map[string]string{"error": err.Error()})
}
// WebSocket starts websocket session. The handler is invoked in a goroutine.
func WebSocket(c echo.Context, handler func(ws *websocket.Conn) error) error {
ws, err := upgrader.Upgrade(c.Response(), c.Request(), nil)
if err != nil {
return Error(c, err)
}
go func() {
var closeMessage []byte
if err := handler(ws); err != nil {
c.Logger().Error(err)
closeMessage = websocket.FormatCloseMessage(
websocket.ClosePolicyViolation, "error: "+err.Error(),
)
} else {
closeMessage = websocket.FormatCloseMessage(
websocket.CloseNormalClosure, "",
)
}
ws.WriteControl(
websocket.CloseMessage, closeMessage, time.Now().Add(wsCloseTimeout),
)
ws.Close()
}()
return nil
}