ERVIN228
ERVIN228

Reputation: 29

How to make an OUTGOING websocket connection request in GO

I find a lot of examples of how to make a websocket service in Go that accepts ws connections, but not one to send them. Since the ws request is initially executed as a normal rest request, I try something like this

request, err := http.NewRequest("GET", "ws://localhost:8081/ws", nil)
if err != nil {
    fmt.Println(err)
    return
}

_, err = http.DefaultClient.Do(request)
if err != nil {
    fmt.Println(err)
    return
}
client := newClient(*websocket.Conn) // how i can get *websocket.Conn?
go client.Read()
go client.Write()
clientsMap.Add(client)

But this obviously doesn't work, I get an unsupported protocol scheme "ws" error. How do I make a ws connection and get *websocket.Conn?

Upvotes: 1

Views: 806

Answers (1)

anantadwi13
anantadwi13

Reputation: 75

If you are using gorilla websocket, you can use Dialer.Dial or Dialer.DialContext from that package. Below is the example on how to use it.

dial, _, err := websocket.DefaultDialer.Dial("ws://localhost:8081/ws", nil)
if err != nil {
    log.Fatalln(err)
}
defer dial.Close()

err = dial.WriteMessage(websocket.TextMessage, []byte("hello"))
if err != nil {
    log.Fatalln(err)
}

err = dial.WriteMessage(websocket.TextMessage, []byte("world"))
if err != nil {
    log.Fatalln(err)
}

For the full code, you can check this.

package main

import (
    "log"
    "net/http"
    "sync"

    "github.com/gorilla/websocket"
)

func main() {
    wg := sync.WaitGroup{}
    wg.Add(2)

    // Server
    go func() {
        defer wg.Done()

        var (
            upgrader = &websocket.Upgrader{}
            stopChan = make(chan struct{})
        )

        http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
            defer func() {
                close(stopChan)
            }()

            upgrade, err := upgrader.Upgrade(w, r, nil)
            if err != nil {
                return
            }
            for {
                msgType, msg, err := upgrade.ReadMessage()
                if err != nil {
                    log.Println("connection closed,", err)
                    return
                }
                log.Println(msgType, string(msg))
            }
        })

        go func() {
            err := http.ListenAndServe("localhost:8081", nil)
            if err != nil {
                log.Fatalln(err)
            }
        }()

        <-stopChan
    }()

    // Dialer (Client)
    go func() {
        defer wg.Done()

        dial, _, err := websocket.DefaultDialer.Dial("ws://localhost:8081/ws", nil)
        if err != nil {
            log.Fatalln(err)
        }
        defer dial.Close()

        err = dial.WriteMessage(websocket.TextMessage, []byte("hello"))
        if err != nil {
            log.Fatalln(err)
        }

        err = dial.WriteMessage(websocket.TextMessage, []byte("world"))
        if err != nil {
            log.Fatalln(err)
        }
    }()

    wg.Wait()
}

// output
// 2022/09/17 07:18:57 1 hello
// 2022/09/17 07:18:57 1 world
// 2022/09/17 07:18:57 connection closed, websocket: close 1006 (abnormal closure): unexpected EOF

Upvotes: 2

Related Questions