dimanche 14 mars 2021

Is it possible to send a web socket message when a rest api is hit?

I need to extend the code of this tutorial to run both a regular rest process and a WebSocket server as part of go routine.

Here is the Go part:

package main

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

    "github.com/gorilla/websocket"
)

var upgrader = websocket.Upgrader{
    ReadBufferSize:  1024,
    WriteBufferSize: 1024,
}

var WS = websocket.Conn{}

func reader(conn *websocket.Conn) {
    for {
        // read in a message
        messageType, p, err := conn.ReadMessage()
        if err != nil {
            log.Println(err)
            return
        }
        // print out that message for clarity
        fmt.Println(string(p))

        if err := conn.WriteMessage(messageType, p); err != nil {
            log.Println(err)
            return
        }
    }
}

func homePage(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Home Page")
}

func restResponsePage(w http.ResponseWriter, r *http.Request) {
    text := []byte("rest response")
    if err := WS.WriteMessage(websocket.TextMessage, text); err != nil {
        log.Println(err)
    }
    fmt.Fprintf(w, "rest response")
}

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

    upgrader.CheckOrigin = func(r *http.Request) bool { return true }

    // upgrade this connection to a WebSocket
    // connection
    WS, err := upgrader.Upgrade(w, r, nil)
    if err != nil {
        log.Println(err)
    }

    log.Println("Client Connected")
    err = WS.WriteMessage(1, []byte("Hi from server!"))
    if err != nil {
        log.Println(err)
    }

    reader(WS)
}

func setupRoutes() {
    http.HandleFunc("/", homePage)
    http.HandleFunc("/restRequest", restResponsePage)
}

func setupWsRoute() {
    http.HandleFunc("/ws", wsEndpoint)
}

func main() {
    fmt.Println("Hello World")

    go func() {
        setupWsRoute()
        log.Fatal(http.ListenAndServe(":8081", nil))
    }()

    setupRoutes()

    log.Fatal(http.ListenAndServe(":8080", nil))
}

And the client index.html:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta http-equiv="X-UA-Compatible" content="ie=edge" />
    <title>Go WebSocket Tutorial</title>
  </head>
  <body>
    <h2>Hello World</h2>

    <script>
        let socket = new WebSocket("ws://127.0.0.1:8081/ws");
        console.log("Attempting Connection...");

        socket.onopen = () => {
            console.log("Successfully Connected");
            socket.send("Hi From the Client!")
        };
        
        socket.onmessage = (event) => {
            console.log("message from Server: ", event.data);
        };

        socket.onclose = event => {
            console.log("Socket Closed Connection: ", event);
            socket.send("Client Closed!")
        };

        socket.onerror = error => {
            console.log("Socket Error: ", error);
        };

    </script>
  </body>
</html>

When I hit the restRequest endpoint, before writing to the restResponsePage response writer w, I want to write a message to the websocket which I declared as a global var WS and initialized inside the reader method when the connection was upgraded.

This is somehow not working, instead, there is an exception and I don't have a clear idea on how to solve it.

Aucun commentaire:

Enregistrer un commentaire