Skip to content

Instantly share code, notes, and snippets.

@mrl22
Last active July 21, 2024 21:54
Show Gist options
  • Save mrl22/a33e714b5ec941f1f4f8afac1064fadc to your computer and use it in GitHub Desktop.
Save mrl22/a33e714b5ec941f1f4f8afac1064fadc to your computer and use it in GitHub Desktop.
Connect to Laravel Reverb from Golang for two-way communication
package main
import (
"encoding/json"
"github.com/gorilla/websocket"
"log"
"net/url"
"os"
"os/signal"
"syscall"
)
// I am a Go newbie, so please excuse my lack of knowledge, but this works. It sends and receives messages/events.
// I could not find a good example of how to connect to a Pusher WebSocket using Go, so I wrote this.
// Important configuration variables
var (
webSocketScheme = "ws" // or "wss" for secure
webSocketHost = "localhost:8080"
webSocketPath = "/app/u9nyjqyzeyj4iy7qegnn" // REVERB_APP_KEY (dont remove /app/)
authToken = "ttlw5knw5xaqkwrocpno" // REVERB_APP_SECRET
authChannel = "test" // Channel configured in routes/channels.php
)
func main() {
u := url.URL{Scheme: webSocketScheme, Host: webSocketHost, Path: webSocketPath}
log.Printf("connecting to %s", u.String())
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
if err != nil {
log.Fatalf("dial error: %v", err)
}
defer c.Close()
// Authenticate if needed
authPayload := map[string]interface{}{
"event": "pusher:subscribe",
"data": map[string]interface{}{
"auth": authToken,
"channel": authChannel,
},
}
authPayloadJSON, err := json.Marshal(authPayload)
if err != nil {
log.Fatalf("marshal auth error: %v", err)
}
err = c.WriteMessage(websocket.TextMessage, authPayloadJSON)
if err != nil {
log.Printf("write auth error: %v", err)
return
}
// Channel to receive messages
messageChan := make(chan []byte)
// Goroutine to read messages
go func() {
defer close(messageChan)
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Printf("read error: %v", err)
return
}
messageChan <- message
}
}()
// Handle system signals for graceful shutdown
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
for {
select {
case message := <-messageChan:
log.Printf("recv: %s", message)
handlePing(c, message)
handleMessage(c, message)
case <-signalChan:
log.Println("shutdown signal received")
return
}
}
}
func handlePing(c *websocket.Conn, message []byte) {
// If the server sends a ping, we need to respond with a pong or we will be disconnected
if string(message) == `{"event":"pusher:ping"}` {
payload := `{"event":"pusher:pong","data":{}}`
err := c.WriteMessage(websocket.TextMessage, []byte(payload))
if err != nil {
return
}
log.Println("sent: " + payload)
}
}
func handleMessage(c *websocket.Conn, message []byte) {
// Parse the incoming message
var msg map[string]interface{}
if err := json.Unmarshal(message, &msg); err != nil {
log.Printf("unmarshal error: %v", err)
return
}
// Handle events
//if event, ok := msg["event"].(string); ok {
//
//}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment