Laravel broadcasting với ably
Dưới đây là đoạn code ở frontend :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="csrf-token" content="{{ csrf_token() }}">
<title>Ably Realtime Chat</title>
<script src="https://cdn.ably.io/lib/ably.min-1.js"></script>
<script>
const ABLY_PUBLIC_KEY = "{{ env('ABLY_KEY_CHINHAN') }}";
const CSRF_TOKEN = document.querySelector('meta[name="csrf-token"]').content;
</script>
<style>
body { font-family: Arial, sans-serif; margin: 20px; }
#messages { max-width: 500px; margin-top: 10px; }
.message { padding: 5px; border-bottom: 1px solid #ddd; }
.private { color: red; }
.public { color: green; }
</style>
</head>
<body>
<h1>Ably Realtime Chat</h1>
<div id="messages"></div> <!-- Hiển thị tin nhắn -->
<script>
const channelsToJoin = ["private-chat", "chat", "public-1"];
function isPrivate(channel) {
return channel.startsWith("private-");
}
@php
if(\Illuminate\Support\Facades\Auth::check()) {
$user_md5 = md5(\Illuminate\Support\Facades\Auth::id());
} else {
$user_md5 = \Illuminate\Support\Str::random();
}
@endphp
const clientId = `{{$user_md5}}`;
const ablyPublicConfig = {
key: ABLY_PUBLIC_KEY, // 🔹 Dùng key cho kênh public
clientId: clientId,
logLevel: "debug",
};
const ablyPrivateConfig = {
authUrl: "/ably/auth", // 🔹 Xác thực cho kênh private
clientId: clientId,
authHeaders: { "X-CSRF-TOKEN": CSRF_TOKEN },
logLevel: "debug",
};
const ablyPublic = new Ably.Realtime(ablyPublicConfig);
const ablyPrivate = new Ably.Realtime(ablyPrivateConfig);
function joinChannel(ablyInstance, channelName) {
const channel = ablyInstance.channels.get(channelName);
channel.subscribe((msg) => {
console.log(`📩 [${channelName}]`, msg.data);
document.getElementById("messages").innerHTML += `
<p class="message ${isPrivate(channelName) ? 'private' : 'public'}">
<strong>${channelName}:</strong> ${msg.data}
</p>`;
});
}
ablyPublic.connection.on("connected", () => {
console.log("🔗 Kết nối kênh Public thành công!");
channelsToJoin.filter(c => !isPrivate(c)).forEach(c => joinChannel(ablyPublic, c));
});
ablyPrivate.connection.on("connected", () => {
console.log("🔒 Kết nối kênh Private thành công!");
channelsToJoin.filter(isPrivate).forEach(c => joinChannel(ablyPrivate, c));
});
ablyPublic.connection.on("failed", (err) => {
console.error("❌ Lỗi kênh Public:", err);
document.getElementById("messages").innerHTML += `<p style="color:red;">❌ Lỗi kênh Public!</p>`;
});
ablyPrivate.connection.on("failed", (err) => {
console.error("❌ Lỗi kênh Private:", err);
document.getElementById("messages").innerHTML += `<p style="color:red;">❌ Lỗi kênh Private!</p>`;
});
</script>
</body>
</html>
Mình xác thực private qua url :
/ably/auth
Ở đây mình code function
public function auth(Request $request)
{
$user = Auth::user();
if (!$user) {
return response()->json(['error' => 'Unauthorized'], 401);
}
$clientId = $request->query('clientId'); // `clientId` phải lấy từ query, không phải `get()`
$ably = new AblyRest(env('ABLY_KEY'));
$token = $ably->auth->requestToken([
'clientId' => $clientId,
'capability' => [
// list kênh đăng kí để cho client nhận
// 'chat' => ['publish', 'subscribe'],
'chat' => [ 'subscribe'],
'private-chat' => ['subscribe']
],
]);
return response()->json($token);
}
trong api key :
ABLY_KEY='TNA36g.x:x-tNEXbrMUEDaMQwSHye8d3A9U-eOyI' ABLY_KEY_CHINHAN=TNA36g.x:x
Ở đây mình dùng ABLY_KEY ở thứ 1 và ABLY_KEY_CHINHAN ở thứ 2
Ở đây mình bắn qua api mà không bắn qua event vì dùng event ko thấy bắn qua :
public function sendapi()
{
$ably = new AblyRest(env('ABLY_KEY'));
$status = $ably->channel('chat')->publish('new-message', 'Thế mới ổn');
}
public function sendapi_private(Request $request){
$ably = new AblyRest(env('ABLY_KEY'));
$status = $ably->channel('private-chat')->publish('new-message', 'Thế mới ổn');
dd($status);
}
Vậy là oke