Websocket market feed implementation in golang

I have written a Go code to implement a market feed WebSocket, but I’m unable to receive messages through the WebSocket.

package main

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

const marketUrl = "https://api.upstox.com/v2/feed/market-data-feed/authorize"
const bearerToken = "MY_AUTH_TOKEN"

func connectWebSocket(wsUrl string) (ws *websocket.Conn, err error) {
	// Establish WebSocket connection
	ws, _, err = websocket.DefaultDialer.Dial(wsUrl, nil)
	if err != nil {
		return nil, err
	}

	// Set a timeout to send a subscription message after 10 seconds
	go func() {
		time.Sleep(1 * time.Second)
		data := map[string]any{
			"guid":   "someguid",
			"method": "sub",
			"data": map[string]any{
				"mode":           "full",
				"instrumentKeys": []string{"NSE_INDEX|Nifty Bank", "NSE_INDEX|Nifty 50"},
			},
		}
		buff, err := json.Marshal(data)
		if err != nil {
			fmt.Println("Error marshalling subscription message:", err)
			return
		}
		fmt.Println(buff)
		if err := ws.WriteMessage(websocket.TextMessage, buff); err != nil {
			fmt.Println("Error sending subscription message:", err)
		}
		fmt.Println("Sent subscription message")
	}()

	return ws, nil
}

func getMarketFeedUrl() (wsUrl string, err error) {
	req, err := http.NewRequest(http.MethodGet, marketUrl, nil)
	if err != nil {
		fmt.Println(err)
		return
	}
	req.Header.Set("Authorization", "Bearer "+bearerToken)

	client := &http.Client{}
	res, err := client.Do(req)
	if err != nil {
		fmt.Println(err)
		return
	}
	defer res.Body.Close()

	if res.StatusCode != http.StatusOK {
		fmt.Println("Failed to authorize")
		return
	}

	response := make(map[string]any)
	err = json.NewDecoder(res.Body).Decode(&response)
	if err != nil {
		fmt.Println(err)
		return
	}

	return response["data"].(map[string]any)["authorizedRedirectUri"].(string), nil
}
func main() {
	// Get the WebSocket URL
	wsUrl, err := getMarketFeedUrl()
	if err != nil {
		fmt.Println("Error getting WebSocket URL:", err)
		return
	}

	ws, err := connectWebSocket(wsUrl)
	if err != nil {
		fmt.Println("Error connecting to WebSocket:", err)
		return
	}
	defer ws.Close()

	fmt.Println("Connected to WebSocket")

	// Read messages from WebSocket
	for {
		_, message, err := ws.ReadMessage()
		if err != nil {
			fmt.Println("Error reading message:", err)
			return
		}
		fmt.Println("Received message:", string(message))
	}
}

My code gets blocked on this particular line

_, message, err := ws.ReadMessage()
1 Like

@Rohit_Devadiga,

Thank you for reaching out.

I managed to run the provided code without any modifications except for the access_token. However, the code doesn’t receive any messages because the subscription feed is sent in the form of TextMessage. When switched to websocket.BinaryMessage, the code functions smoothly, receiving market updates without any problems. You’ll need to focus on integrating the proto file to decode the messages.

Appreciate your attention to this matter.

Thank you!

Thank you for your assistance @shanmu

1 Like