Как правильно настроить WebSocket для мини-приложения в Телеграм?

Я пытаюсь настроить подключение мини-приложения Telegram через WebSocket, но сталкиваюсь с ошибкой: "websocket: the client is not using the websocket protocol: 'upgrade' token not found in 'Connection' header." Я использую туннель в Visual Studio Code для доступа к своей локальной сети на порту 8080.

Мой локальный сервер запускается с помощью следующей функции: 
<pre><code class="go">func MustStartHTTPServer() {
	http.HandleFunc("/", HandleWebsocketConnection)

	if err := http.ListenAndServe(":"+os.Getenv("HTTP_PORT"), nil); err != nil {
		slog.Error("Cant start http+ws server", "err", err.Error())
		os.Exit(1)
	}

	slog.Info("start server", "port", os.Getenv("HTTP_PORT"))
}</code></pre>

Функция HandleWebsocketConnection выглядит следующим образом: 
<pre><code class="go">func HandleWebsocketConnection(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Upgrade", "websocket")
	w.Header().Set("Connection", "upgrade")

	conn, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		slog.Error("while upgrading to websocket", "error", err)
		return
	}

	slog.Info("New Websocket connection", "ip", conn.RemoteAddr())
	for {
		_, msg, err := conn.ReadMessage()
		if err != nil {
			slog.Error("error while reading", "err", err)
			break
		}

		err = conn.WriteMessage(websocket.TextMessage, msg)
		if err != nil {
			slog.Error("error while writing", "err", err)
			break
		}
	}
}</code></pre>

Хотя я устанавливаю нужные заголовки (headers) и они правильно отображаются в ResponseWriter, ошибка продолжает возникать. Как я могу решить эту проблему?
  • 3 января 2025 г. 18:33
Ответы на вопрос 1
Для успешного подключения к WebSocket серверу из мини-приложения в Telegram, необходимо убедиться, что заголовки, которые вы устанавливаете, могут правильно обрабатываться клиентом. Ошибка, которую вы видите, связана с тем, что клиент не воспринимает ваш ответ как WebSocket.

Вот несколько моментов, на которые стоит обратить внимание:

1. **Проверка метода подключения**:
   Убедитесь, что ваш WebSocket сервер корректно обрабатывает только те запросы, которые действительно являются запрашиваемыми для WebSocket. Также важно проверять методы запросов, так как WebSocket использует метод `GET`.

   Добавьте проверку метода:
   ```go
   if r.Method != http.MethodGet {
       http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
       return
   }
   ```

2. **Проверка заголовков**:
   WebSocket запрос должен содержать определённые заголовки. Убедитесь, что клиент посылает заголовки `Upgrade: websocket` и `Connection: Upgrade`. Если эти заголовки отсутствуют, соединение не установлен.

   Пример проверки заголовков:
   ```go
   if r.Header.Get("Upgrade") != "websocket" {
       http.Error(w, "Upgrade header is missing", http.StatusBadRequest)
       return
   }
   if r.Header.Get("Connection") != "Upgrade" {
       http.Error(w, "Connection header is missing", http.StatusBadRequest)
       return
   }
   ```

3. **Правильный порядок установки заголовков**:
   В вашем коде вы устанавливаете заголовки **после** того, как уже начали обрабатывать WebSocket соединение. Вам нужно установить заголовки перед вызовом `upgrader.Upgrade`.

   Правильный порядок:
   ```go
   func HandleWebsocketConnection(w http.ResponseWriter, r *http.Request) {
       if r.Method != http.MethodGet {
           http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
           return
       }

       // Установка заголовков перед вызовом upgrader
       w.Header().Set("Upgrade", "websocket")
       w.Header().Set("Connection", "upgrade")
       
       conn, err := upgrader.Upgrade(w, r, nil)
       if err != nil {
           slog.Error("while upgrading to websocket", "error", err)
           return
       }
   }
   ```

4. **Правильная конфигурация**:
   Также убедитесь, что ваш локальный сервер настроен на корректный порт, и ваш туннель (например, ngrok или другой) работает и перенаправляет трафик правильно. Вам нужно использовать URL, который генерирует ваш туннель (например, `https://<your-tunnel-url>`).

5. **Безопасность**:
   Если вы используете Telegram для мини-приложений, убедитесь, что ваше соединение безопасно (HTTPS), так как WebSocket соединения могут быть отклонены, если не будет защищенного соединения.

После того как вы проверите и скорректируете все из выше приведенных пунктов, попробуйте снова подключиться к вашему WebSocket серверу из мини-приложения Telegram.
Похожие вопросы