Розробка WebSocket API для веб-застосунку

Наша компанія займається розробкою, підтримкою та обслуговуванням сайтів будь-якої складності. Від простих односторінкових сайтів до масштабних кластерних систем, побудованих на мікро сервісах. Досвід розробників підтверджено сертифікатами від вендорів.
Розробка та обслуговування будь-яких видів сайтів:
Інформаційні сайти або веб-програми
Сайти візитки, landing page, корпоративні сайти, онлайн каталоги, квіз, промо-сайти, блоги, ресурси новин, інформаційні портали, форуми, агрегатори
Сайти або веб-програми електронної комерції
Інтернет-магазини, B2B-портали, маркетплейси, онлайн-обмінники, кешбек-сайти, біржі, дропшиппінг-платформи, парсери товарів
Веб-програми для управління бізнес-процесами
CRM-системи, ERP-системи, корпоративні портали, системи управління виробництвом, парсери інформації
Сайти або веб-програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, конструктори сайтів, портали надання електронних послуг, відеохостинги, тематичні портали

Це лише деякі з технічних типів сайтів, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Пропоновані послуги
Показано 1 з 1 послугУсі 2065 послуг
Розробка WebSocket API для веб-застосунку
Середня
~3-5 робочих днів
Часті питання
Наші компетенції:
Етапи розробки
Останні роботи
  • image_website-b2b-advance_0.png
    Розробка сайту компанії B2B ADVANCE
    1262
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1171
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    874
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1094
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    831
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Розробка веб-сайту для компанії ФІКСПЕР
    851

Розробка WebSocket API для веб-додатку

WebSocket — протокол, що забезпечує двонаправлений канал зв'язку між клієнтом і сервером по одному TCP-з'єднанню. Підходить для: real-time-чату, live-сповіщень, спільного редагування, біржевих котирувань, онлайн-ігор.

Коли потрібен WebSocket

Задача WebSocket Polling SSE
Чат, спільна робота Погано Ні (односпрямований)
Сповіщення Прийнятно
Котирування/аналітика Погано
Завантаження файлу з прогресом Не потрібно Не потрібно
REST CRUD Не потрібно

Базова реалізація (Node.js + ws)

import { WebSocketServer } from 'ws';
import { createServer } from 'http';

const server = createServer(app);
const wss = new WebSocketServer({ server });

// Зберігання з'єднань: кімната → Set<WebSocket>
const rooms = new Map<string, Set<WebSocket>>();

wss.on('connection', (ws, req) => {
  const roomId = new URL(req.url!, 'http://x').searchParams.get('room');
  if (!roomId) return ws.close(4000, 'Missing room');

  // Додаємо в кімнату
  if (!rooms.has(roomId)) rooms.set(roomId, new Set());
  rooms.get(roomId)!.add(ws);

  ws.on('message', (data) => {
    const message = JSON.parse(data.toString());
    // Broadcast у кімнату
    rooms.get(roomId)?.forEach(client => {
      if (client !== ws && client.readyState === WebSocket.OPEN) {
        client.send(JSON.stringify(message));
      }
    });
  });

  ws.on('close', () => {
    rooms.get(roomId)?.delete(ws);
  });
});

Протокол повідомлень

Структурований JSON-протокол замість raw тексту:

// Типи повідомлень
type WSMessage =
  | { type: 'join_room'; roomId: string; userId: string }
  | { type: 'message'; roomId: string; text: string; timestamp: number }
  | { type: 'typing'; roomId: string; userId: string }
  | { type: 'error'; code: string; message: string };

Аутентифікація

WebSocket не підтримує кастомні заголовки під час handshake. Варіанти:

  • Token у query stringws://api.com/ws?token=eyJ... (видно у логах, менш безпечно)
  • Cookie — при ws:// на тому ж домені, withCredentials: true
  • First message auth — перше повідомлення після підключення — аутентифікація
ws.on('connection', (socket) => {
  let authenticated = false;
  const authTimeout = setTimeout(() => {
    if (!authenticated) socket.close(4001, 'Auth timeout');
  }, 5000);

  socket.once('message', (data) => {
    const { type, token } = JSON.parse(data.toString());
    if (type === 'auth' && validateToken(token)) {
      authenticated = true;
      clearTimeout(authTimeout);
      socket.send(JSON.stringify({ type: 'auth_success' }));
    } else {
      socket.close(4001, 'Invalid token');
    }
  });
});

Горизонтальне масштабування

Проблема: при кількох серверах клієнт A підключений до сервера 1, клієнт B — до сервера 2. Повідомлення від A не дійде до B.

Рішення — Redis Pub/Sub для міжсерверної комунікації:

import { createClient } from 'redis';
const pub = createClient();
const sub = createClient();

// Сервер отримує повідомлення від клієнта
ws.on('message', async (data) => {
  await pub.publish(`room:${roomId}`, data.toString());
});

// Всі сервери підписані і доставляють своїм клієнтам
sub.subscribe(`room:${roomId}`, (message) => {
  rooms.get(roomId)?.forEach(client => {
    if (client.readyState === WebSocket.OPEN) client.send(message);
  });
});

Socket.io проти нативного WebSocket

Socket.io — надстройка над WebSocket з fallback на long polling, автоматичним переподключенням, кімнатами, namespace й acks:

io.to(roomId).emit('message', { text: 'Hello' }); // замість ручного broadcast

Нативний WebSocket — менше overhead, повний контроль, без лишніх абстракцій. Рекомендується при > 10K з'єднань або коли важлива задержка.

Heartbeat і reconnect

Браузери і проксі закривають idle-з'єднання. Ping/pong кожні 30 секунд:

wss.on('connection', (ws) => {
  let alive = true;
  ws.on('pong', () => { alive = true; });

  const interval = setInterval(() => {
    if (!alive) return ws.terminate();
    alive = false;
    ws.ping();
  }, 30000);

  ws.on('close', () => clearInterval(interval));
});

Терміни

WebSocket-сервер з кімнатами, аутентифікацією, Redis Pub/Sub: 1–2 тижні. З Socket.io, протоколом повідомлень, обробкою reconnect і тестами: 2–3 тижні.