golang

Golang WebSocket

In this article, we will show you how to create a basic web socket in Go. We will build a simple server that repeats back what you say. This will help introduce you to the world of WebSocket and the gorilla WebSocket package.

Required Imports

The first thing to do is to import the required packages. For this project, we will need the fmt package, net/http, and the gorilla package.

We can do these imports as:

import (
    "fmt"
    "net/http"
    "github.com/gorilla/websocket"
)

Once imported, we can begin building our server.

Upgrade HTTP connection

The first step in our project is to take a HTTP connection and upgrade it to a WebSocket . We can do this using the websocket.Upgrade struct. It takes Read and Write Buffer size as defined in the source code below:

https://pkg.go.dev/github.com/gorilla/websocket#Upgrader

For our example, we will use the default options but set the CheckOrigin to a function that returns true. This will prevent the server from blocking the connection due to CORS.

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

Add Handler

Next, let us a HTTP handler when a client hits the /echo endpoint. We will define later in the main function.

func echo(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    iferr != nil {
        log.Fatal(err)
        return
    }
    defer conn.Close()
    for {
        mt, message, err := conn.ReadMessage()
        iferr != nil {
            log.Fatal(err)
            break
        }
        fmt.Printf("recv: %s", message)
        err = conn.WriteMessage(mt, message)
        iferr != nil {
            log.Fatal(err)
            break
        }
    }
}

In the example above, we define a function that takes the ResponseWriter and a pointer to the http.Response.

We the upgrade the HTTP connection to the WebSocket protocol using the Upgrader function. Next, we use a for loop to listen and read incoming messages. We then print the message to the console and echo the message back to the client.

Add WebSocket Endpoint

The next step is to add a simple http handler for the WebSocket endpoint. We can use the function as:

func home(w http.ResponseWriter, r *http.Request) {

websocketTemplate.Execute(w, "ws://"+r.Host+"/echo")

}

Create Client

To interact with the WebSocket serve, we need to create a client. We can do this by creating a simple HTML file from that uses JavaScript to open a WebSocket connection to the server. An example code is as shown:

index.html

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="UTF-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="width=device-width, initial-scale=1.0">

<title>Simple Websocket Connection</title>

</head>

<body>

<input id="input" type="text" />

<button onclick="send()">Send</button>

<pre id="output"></pre>

<script>

const input = document.getElementById("input");
const output = document.getElementById("output");
const socket = new WebSocket("ws://localhost:8000/echo");

socket.onopen = function () {
output.innerHTML += "Status: Connected\n";
    };

socket.onmessage = function (e) {
output.innerHTML += "Server: " + e.data + "\n";
    };
functionsend() {
socket.send(input.value);
input.value = "";
    }


</script>

</body>

</html>

Run Server

The last step is to define the routes and call the HTTP handlers in the main function. The code is as shown:

funcmain() {
    http.HandleFunc("/echo", echo)
    http.HandleFunc("/", home)
    http.ListenAndServe(":8000", nil)
}

Save the files and run:

go run ws.go

Open the index.html file in your browser. You should see a connected message once the browser establishes a connection.

If you type any message into the field, the server responds it back.

The full source code of the program is as shown:

package main

import (
    "fmt"
    "log"
    "net/http"

    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    CheckOrigin: func(r *http.Request) bool {
        return true
    },
}

funcecho(w http.ResponseWriter, r *http.Request) {
    conn, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Fatal(err)
        return
    }
    deferconn.Close()
    for {
        mt, message, err := conn.ReadMessage()
        if err != nil {
            log.Fatal(err)
            break
        }
        fmt.Printf("recv: %s", message)
        err = conn.WriteMessage(mt, message)
        if err != nil {
            log.Fatal(err)
            break
        }
    }
}
funchome(w http.ResponseWriter, r *http.Request) {
    http.ServeFile(w, r, "index.html")
}

funcmain() {
    http.HandleFunc("/echo", echo)
    http.HandleFunc("/", home)
    http.ListenAndServe(":8000", nil)
}

Conclusion

This was a beginner’s guide to working with WebSocket in Go. In this guide, we covered how to upgrade a http connection to WebSocket protocol, read messages and responds messages back to the client.

About the author

John Otieno

My name is John and am a fellow geek like you. I am passionate about all things computers from Hardware, Operating systems to Programming. My dream is to share my knowledge with the world and help out fellow geeks. Follow my content by subscribing to LinuxHint mailing list