Socketra Dökümantasyonu

Socketra, backend'inizden yayınladığınız olayları bağlı client'lara gerçek zamanlı ileten bir WebSocket katmanıdır. Bu rehber, client ve backend tarafını uçtan uca kurmanızı sağlar.

Mimari

Socketra üç parçadan oluşan bir akışa dayanır. Veri izolasyonu kanallar (odalar) ile sağlanır: bir istemci yalnızca abone olduğu kanalın mesajlarını alır.

  • Client (React Native / Web) — kullanıcıya özel token ile bağlanır, bir kanala subscribe olur ve o kanalın olaylarını dinler.
  • Socketra — bağlantıyı doğrular, kanal aboneliğini projenizin backend'ine yetkilendirir, mesajları yalnızca ilgili kanala iletir.
  • Backend'iniz (Laravel / Node.js) — bir olay olduğunda Redis'e, hedef kanalı belirterek yayın yapar.
akış
  Backend (Laravel/Node)          Socketra                  Client (RN/Web)
        │                            │                            │
        │                            │  ◀── subscribe("private-conversation-9")
        │                            │      (auth_endpoint'te doğrulanır)
        │  Redis PUBLISH             │                            │
        │  project_42_events  ─────▶ │                            │
        │  {event, data,             │   sadece o odaya:          │
        │   channel:"private-        │   emit "event"             │
        │   conversation-9"}         │ ─────────────────────────▶ │  socket.on("event")
        │                            │  (başka kanaldakiler almaz)│

Temel Kavramlar

KavramAçıklama
ProjeGerçek zamanlı alanınız. Her projenin benzersiz bir ID'si ve app_key'i vardır.
app_keysk_ ile başlayan gizli anahtar. Yalnızca backend'de kullanılır — tarayıcıya gömülmez.
tokenKullanıcıya özel, sizin API'nizin ürettiği kimlik. Tarayıcı bununla bağlanır.
Kanal (oda)İzolasyon birimi (örn. private-conversation-9). İstemci abone olduğu kanalın mesajlarını alır.
auth_endpointProjenizin, "bu kullanıcı bu kanala girebilir mi?" sorusunu yanıtlayan API adresi.
Eventİletilen olayın adı (örn. new-message). Client bu adla dinler.

İhtiyacınız olanlar

  • Bir Socketra hesabı ve oluşturulmuş bir proje.
  • Projenizin ID ve app_key değerleri.
  • Backend tarafında Redis'e erişim (yayın yapmak için).
ℹ️
Soldaki menüden platformunuzu seçerek adım adım kuruluma geçebilirsiniz. Client tarafı olayları dinler, backend tarafı olayları yayınlar.

Kanallar & İzolasyon

Socketra'da veri, projeye değil kanala gider. Bir istemci yalnızca yetkilendirilip abone olduğu kanalın mesajlarını alır — böylece kullanıcı A'nın verisi kullanıcı B'ye düşmez.

Kanal Tipleri

ÖnekYetkiKullanım
public-GerekmezHerkese açık yayınlar (örn. public-announcements).
private-auth_endpointKişiye/gruba özel (örn. private-conversation-9).
presence-auth_endpointÖzel + kimlerin çevrimiçi olduğunu izleme.
⚠️
Önek taşımayan kanal adları reddedilir. Özel bir kanala abonelik, projenizin auth_endpoint'i onaylamadıkça kabul edilmez.

auth_endpoint Tanımlama

Projenizin ayarlarına, Socketra'nın abonelik yetkisini soracağı bir API adresi ekleyin (Dashboard → Proje → Config, anahtar: auth_endpoint):

project config
auth_endpoint = https://api.siteniz.com/socketra/auth

Bir istemci özel kanala abone olmak istediğinde Socketra bu adrese şu isteği yapar:

Socketra → sizin API'niz
POST /socketra/auth
Authorization: Bearer <kullanıcının token'ı>
Content-Type: application/json

{ "socket_id": "abc123", "channel_name": "private-conversation-9" }

# 200 → izin verilir   |   401/403 → reddedilir

auth_endpoint Örneği (Laravel)

Token'dan kullanıcıyı bulun ve o kanala erişim hakkını kontrol edin:

routes/api.php
Route::post('/socketra/auth', function (Request $request) {
    $user = auth()->user();                 // Bearer token'dan
    if (!$user) return response('Unauthorized', 401);

    $channel = $request->input('channel_name');   // private-conversation-9
    $id = (int) str_replace('private-conversation-', '', $channel);

    // Kullanıcı bu konuşmanın katılımcısı mı?
    if (!$user->conversations()->where('id', $id)->exists()) {
        return response('Forbidden', 403);
    }
    return response()->json(['ok' => true]);   // 200 = izin
});
💡
Yetki kararı tamamen sizde kalır — Socketra sadece sizin "evet" demenizi bekler. Bu, Pusher private-channel modeliyle birebir aynıdır.
React NativeExposocket.io-client

React Native Entegrasyonu

Mobil uygulamanızı Socketra'ya bağlayın, olayları dinleyin ve mesaj gönderin.

1 Kurulum

Socket.IO client kütüphanesini projenize ekleyin:

terminal
# npm
npm install socket.io-client

# veya yarn
yarn add socket.io-client

2 Bağlan (kullanıcı token'ı ile)

Tarayıcı/mobil istemci gizli app_key'i değil, sizin API'nizin ürettiği kullanıcı token'ını kullanır:

socket.js
import io from 'socket.io-client';

const PROJECT_ID = 42;
const userToken = await getMyApiToken();  // kendi giriş sisteminizden

export const socket = io(`https://socketra.net/project-${PROJECT_ID}`, {
  auth: { token: userToken },     // app_key YOK — sadece kullanıcı token'ı
  transports: ['websocket'],
  reconnection: true,
});
🔒
Bağlanmak tek başına hiçbir veri vermez. Erişim, bir kanala abone olduğunuzda projenizin auth_endpoint'inde doğrulanır.

3 Kanala Abone Ol ve Dinle

Bir kanala subscribe olun; onay gelince o kanalın olaylarını dinleyin:

listeners.js
socket.on('connect', () => {
  // Konuşma kanalına katıl (auth_endpoint'te yetkilendirilir)
  socket.emit('subscribe', { channel: 'private-conversation-9' }, (res) => {
    if (res.ok) console.log('✅ Abone olundu', res.channel);
    else console.log('❌ Reddedildi:', res.error);
  });
});

// Backend'in bu kanala yayınladığı olay
socket.on('new-message', (data) => console.log('Yeni mesaj:', data));

// Diğer istemcilerin bu kanala gönderdiği mesajlar
socket.on('message-received', (payload) => console.log(payload.channel, payload.data));

socket.on('connect_error', (err) => console.log('Auth hatası:', err.message));

4 Tam Örnek: Canlı Sohbet

Bağlantı, dinleme ve mesaj gönderimini birleştiren eksiksiz bir bileşen:

ChatScreen.jsx
import React, { useEffect, useState, useRef } from 'react';
import { View, Text, TextInput, Button, FlatList } from 'react-native';
import io from 'socket.io-client';

export default function ChatScreen() {
  const [messages, setMessages] = useState([]);
  const [text, setText] = useState('');
  const socketRef = useRef(null);

  const CHANNEL = 'private-conversation-9';

  useEffect(() => {
    const socket = io('https://socketra.net/project-42', {
      auth: { token: '<kullanıcı-token>' },   // app_key değil
      transports: ['websocket'],
    });
    socketRef.current = socket;

    socket.on('connect', () => {
      socket.emit('subscribe', { channel: CHANNEL });   // odaya katıl
    });

    socket.on('message-received', (payload) => {
      if (payload.channel === CHANNEL)
        setMessages((prev) => [...prev, payload]);
    });

    return () => socket.disconnect();  // ekran kapanınca temizle
  }, []);

  const send = () => {
    if (!text.trim()) return;
    // Yalnızca bu kanaldakilere gider
    socketRef.current.emit('client-chat', { channel: CHANNEL, data: { text } });
    setText('');
  };

  return (
    <View style={{ flex: 1, padding: 16 }}>
      <FlatList
        data={messages}
        keyExtractor={(_, i) => String(i)}
        renderItem={({ item }) => <Text>{item.data?.text}</Text>}
      />
      <TextInput value={text} onChangeText={setText} placeholder="Mesaj…" />
      <Button title="Gönder" onPress={send} />
    </View>
  );
}
💡
Client message/client-chat gönderirken mutlaka channel belirtir; Socketra bunu yalnızca o kanala abone olanlara message-received olarak iletir. Kalıcı işlem (DB kaydı) için mesajı backend'inize de gönderin.
BrowserVanilla JSCDN

Web / JavaScript

Herhangi bir web sayfasına birkaç satırda gerçek zamanlı bağlantı ekleyin.

1 Kütüphaneyi Ekle

NPM ile (Vite, Webpack vb.) veya doğrudan CDN üzerinden:

index.html
<!-- CDN -->
<script src="https://cdn.socket.io/4.8.1/socket.io.min.js"></script>

2 Bağlan ve Dinle

app.js
const socket = io('https://socketra.net/project-42', {
  auth: { token: '<kullanıcı-token>' },   // app_key değil
});

socket.on('connect', () => {
  socket.emit('subscribe', { channel: 'private-user-7' });
});

// Backend'in bu kanala yayınladığı olay
socket.on('notification', (data) => showToast(data.title, data.body));

// Mesaj gönder → yalnızca bu kanala abone olanlara gider
document.querySelector('#send').onclick = () => {
  socket.emit('message', { channel: 'private-user-7', data: { text: input.value } });
};
ℹ️
Sayfanızın origin'i, Socketra'nın CORS listesinde olmalıdır. Kendi domain'inizi eklemek için Socketra yapılandırmasında CORS_ORIGIN değişkenini kullanın.
Laravel 10/11PHP 8.1+Redis

Laravel Entegrasyonu

Laravel backend'inizden bir olay olduğunda Socketra'ya yayın yapın. Client'lar bunu anında alır.

1 Redis Kurulumu

Laravel, Redis ile yayın yapmak için predis/predis veya phpredis uzantısını kullanır. Predis en kolayıdır:

terminal
composer require predis/predis

.env dosyanızda Redis'i Socketra ile aynı sunucuya yönlendirin:

.env
REDIS_CLIENT=predis
REDIS_HOST=127.0.0.1
REDIS_PORT=6379
REDIS_PASSWORD=null

2 Socketra Servisi

Yayın mantığını tek bir yerde toplamak için küçük bir yardımcı sınıf oluşturun. Önemli: Laravel, kanal adlarına bir önek (laravel_database_) ekleyebilir; Socketra'nın beklediği ham kanal adını göndermek için alttaki istemciyi doğrudan kullanıyoruz.

app/Services/Socketra.php
<?php

namespace App\Services;

use Illuminate\Support\Facades\Redis;

class Socketra
{
    /**
     * Bir projeye olay yayınlar.
     * @param int         $projectId  Proje ID'si
     * @param string      $event      Client'ın dinleyeceği olay adı
     * @param array       $data       Gönderilecek veri
     * @param string|null $channel    Hedef kanal (oda). null ise proje geneline yayılır.
     */
    public static function emit(int $projectId, string $event, array $data, ?string $channel = null): void
    {
        $redisChannel = "project_{$projectId}_events";
        $payload = json_encode([
            'event'   => $event,
            'data'    => $data,
            'channel' => $channel,   // örn: private-conversation-9
        ]);

        // ->client() alttaki phpredis/predis istemcisidir; önek eklemez.
        Redis::connection()->client()->publish($redisChannel, $payload);
    }
}

3 Kullanım

Controller, Job veya Event listener'ınızdan çağırın:

MessageController.php
use App\Services\Socketra;

public function store(Request $request)
{
    $message = Message::create($request->validated());

    // Yalnızca ilgili konuşma kanalına "new-message" gönder
    Socketra::emit(42, 'new-message', [
        'id'   => $message->id,
        'text' => $message->text,
        'user' => $message->user->name,
    ], "private-conversation-{$message->conversation_id}");

    return response()->json($message, 201);
}

Client tarafında karşılığı:

client
socket.on('new-message', (data) => {
  console.log(data.text, '—', data.user);
});

4 Laravel Event ile (opsiyonel)

Yayını Laravel'in event sistemine bağlamak isterseniz bir listener kullanın:

app/Listeners/BroadcastToSocketra.php
public function handle(MessageSent $event): void
{
    Socketra::emit(
        $event->message->project_id,
        'new-message',
        $event->message->toArray()
    );
}
⚠️
Kanal adı kuralı: Kanal project_{ID}_ ile başlamalı ve en az üç _ parçası içermelidir (örn. project_42_events). Aksi halde Socketra mesajı ilgili projeye yönlendiremez.
Node.js 18+ioredisExpress

Node.js Entegrasyonu

Node backend'inizden Redis'e yayın yaparak client'lara gerçek zamanlı olay gönderin.

1 Kurulum

terminal
npm install ioredis

2 Yayın İstemcisi

Socketra ile aynı Redis sunucusuna bağlanan bir publisher oluşturun:

socketra.js
const Redis = require('ioredis');

const pub = new Redis({
  host: '127.0.0.1',
  port: 6379,
  // password: process.env.REDIS_PASSWORD,
});

/**
 * Bir projeye olay yayınlar.
 * @param {string} [channel] Hedef kanal (oda). Boşsa proje geneline yayılır.
 */
function emit(projectId, event, data, channel = null) {
  const redisChannel = `project_${projectId}_events`;
  return pub.publish(redisChannel, JSON.stringify({ event, data, channel }));
}

module.exports = { emit };

3 Kullanım (Express)

routes.js
const { emit } = require('./socketra');

app.post('/messages', async (req, res) => {
  const message = await db.messages.create(req.body);

  // Yalnızca ilgili konuşma kanalına gönder
  await emit(42, 'new-message', {
    id: message.id,
    text: message.text,
    user: message.userName,
  }, `private-conversation-${message.conversationId}`);

  res.status(201).json(message);
});
💡
Publisher bağlantısını uygulama başında bir kez oluşturun ve yeniden kullanın; her istekte yeni bağlantı açmayın.

4 Global Yayın (tüm projeler)

Sistem geneli bir duyuru için *_database_* desenli bir kanala yayın yapabilirsiniz. Bu, tüm bağlı client'lara {kanal}:{event} olarak iletilir:

broadcast.js
pub.publish(
  'system_database_alerts',
  JSON.stringify({ event: 'maintenance', data: { at: '02:00' } })
);
// Client: socket.on('system_database_alerts:maintenance', ...)

Event Referansı

Client ile Socketra arasında akan yerleşik olaylar.

Client → Sunucu (emit)

OlayPayloadSonuç
subscribe{ channel }, callbackKanala katılım; özel kanallar auth_endpoint'te yetkilendirilir. Ack: { ok, channel } ya da { ok:false, error }.
unsubscribe{ channel }Kanaldan ayrılır.
message{ channel, data }Sadece o kanala abone olanlara message-received gider. Abone değilse reddedilir.
client-chat{ channel, data }message ile aynı davranış.
pingcallbackSunucu 'pong' ile yanıtlar.

Sunucu → Client (on)

Olayİçerik
connectBağlantı ve doğrulama başarılı (henüz veri erişimi yok).
disconnectBağlantı kesildi (reason parametresi ile).
connect_errorDoğrulama başarısız (geçersiz app_key/token, pasif proje).
message-receivedBir client kanala mesaj gönderdiğinde o kanaldakilere gider: { socketId, projectId, channel, data, timestamp }.
{özel}Backend'inizin ilgili kanala yayınladığı olaylar (örn. new-message).

Redis Yayın Formatı

AlanDeğer
Kanal deseniproject_{ID}_{ad} (örn. project_42_events)
Mesaj gövdesi{ "event": "olay-adi", "data": {…}, "channel": "private-…" }
channelVerilirse yalnızca o odaya iletilir; boş/yoksa proje geneline yayılır.
Client dinlemesocket.on('olay-adi', data => …)

Güvenlik İyi Uygulamalar

Üretimde güvenli bir kurulum için dikkat edilmesi gerekenler.

app_key vs token

  • app_key yalnızca backend'de: sk_ anahtarı gizli bir sunucu sırrıdır; tarayıcıya/mobil bundle'a asla gömmeyin. Yayın için backend'de kullanılır.
  • Tarayıcı token ile bağlanır: İstemciler, sizin API'nizin ürettiği kullanıcıya özel token'ı kullanır. Böylece gizli anahtar hiçbir zaman istemciye inmez.
  • Sızarsa yenileyin: Dashboard'dan tek tıkla yeni app_key üretebilirsiniz; eski anahtar anında geçersiz olur.

Veri İzolasyonu

  • Kanal bazlı: Veri projeye değil kanala gider. İstemci yalnızca abone olduğu kanalın mesajlarını alır.
  • Sunucu tarafı yetki: Özel kanal aboneliği, kararı sizin verdiğiniz auth_endpoint'te doğrulanır. Kimse rastgele bir konuşmaya giremez.
  • Bağlantı ≠ erişim: Bağlanmak tek başına hiçbir veri vermez; erişim abonelikle başlar.

Bağlantı Kuralları

  • Yalnızca status = active olan projeler bağlantı kabul eder.
  • Web istemcileri için origin, sunucunun CORS listesinde olmalıdır.
  • Maksimum mesaj boyutu 1 MB ile sınırlıdır.
  • Üretimde wss:// (TLS) kullanın.

Üretim Kontrol Listesi

  • wss:// (TLS) üzerinden bağlanın — düz ws:// kullanmayın.
  • Backend Redis'inizi dışarıya kapatın; yalnızca Socketra ve backend erişebilsin.
  • İstemciden gelen verilere güvenmeyin; kalıcı işlemleri backend'de doğrulayın.
  • Yeniden bağlanma (reconnection) ayarlarını mobilde etkin tutun.
🔒
Sunucu tarafında rate limiting, helmet güvenlik başlıkları ve HMAC token doğrulaması varsayılan olarak etkindir.