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.
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
| Kavram | Açıklama |
|---|---|
| Proje | Gerçek zamanlı alanınız. Her projenin benzersiz bir ID'si ve app_key'i vardır. |
| app_key | sk_ ile başlayan gizli anahtar. Yalnızca backend'de kullanılır — tarayıcıya gömülmez. |
| token | Kullanı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_endpoint | Projenizin, "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).
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
| Önek | Yetki | Kullanım |
|---|---|---|
public- | Gerekmez | Herkese açık yayınlar (örn. public-announcements). |
private- | auth_endpoint | Kişiye/gruba özel (örn. private-conversation-9). |
presence- | auth_endpoint | Özel + kimlerin çevrimiçi olduğunu izleme. |
auth_endpoint Tanımlama
Projenizin ayarlarına, Socketra'nın abonelik yetkisini soracağı bir API adresi ekleyin (Dashboard → Proje → Config, anahtar: auth_endpoint):
auth_endpoint = https://api.siteniz.com/socketra/auth
Bir istemci özel kanala abone olmak istediğinde Socketra bu adrese şu isteği yapar:
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:
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
});
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:
# 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:
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,
});
3 Kanala Abone Ol ve Dinle
Bir kanala subscribe olun; onay gelince o kanalın olaylarını dinleyin:
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:
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>
);
}
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:
<!-- CDN -->
<script src="https://cdn.socket.io/4.8.1/socket.io.min.js"></script>
2 Bağlan ve Dinle
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 } });
};
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:
composer require predis/predis
.env dosyanızda Redis'i Socketra ile aynı sunucuya yönlendirin:
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.
<?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:
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ığı:
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:
public function handle(MessageSent $event): void
{
Socketra::emit(
$event->message->project_id,
'new-message',
$event->message->toArray()
);
}
Node.js Entegrasyonu
Node backend'inizden Redis'e yayın yaparak client'lara gerçek zamanlı olay gönderin.
1 Kurulum
npm install ioredis
2 Yayın İstemcisi
Socketra ile aynı Redis sunucusuna bağlanan bir publisher oluşturun:
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)
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);
});
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:
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)
| Olay | Payload | Sonuç |
|---|---|---|
subscribe | { channel }, callback | Kanala 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ış. |
ping | callback | Sunucu 'pong' ile yanıtlar. |
Sunucu → Client (on)
| Olay | İçerik |
|---|---|
connect | Bağlantı ve doğrulama başarılı (henüz veri erişimi yok). |
disconnect | Bağlantı kesildi (reason parametresi ile). |
connect_error | Doğrulama başarısız (geçersiz app_key/token, pasif proje). |
message-received | Bir 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ı
| Alan | Değer |
|---|---|
| Kanal deseni | project_{ID}_{ad} (örn. project_42_events) |
| Mesaj gövdesi | { "event": "olay-adi", "data": {…}, "channel": "private-…" } |
channel | Verilirse yalnızca o odaya iletilir; boş/yoksa proje geneline yayılır. |
| Client dinleme | socket.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.