TsgcWS_API_Pusher 组件已更新,以符合最新的
Pusher Channels protocol specification.
此版本引入了私有加密频道支持、四个新的存在与缓存频道事件、
两个新的 REST API 端点、现有端点的增强查询参数以及若干错误修复。
所有更改均向后兼容——现有代码无需修改即可继续运行。
目录
1. 私有加密频道支持
Pusher Channels 支持私有加密频道,通过 NaCl Secretbox(XSalsa20-Poly1305)提供事件数据的端到端加密。
Pusher 服务器永远看不到明文——只有通信双方客户端才能解密消息。以下两种新频道类型已添加至
TsgcWSPusherChannels 枚举:
| 枚举值 | 频道前缀 | 描述 |
|---|---|---|
pscPrivateEncryptedChannel |
private-encrypted- |
端到端加密私有频道。数据负载使用每个频道的共享密钥加密。 |
pscPrivateEncryptedCacheChannel |
private-encrypted-cache- |
同上,并具有缓存频道行为——最近一次事件会发送给新订阅者。 |
TsgcWSPusherResponseAuthentication 类现在包含
SharedSecret 属性。订阅
private-encrypted- 频道时,您的授权端点必须返回
Base64 编码的每频道共享密钥。请在
OnPusherAuthentication 事件处理器中设置此值:
procedure TForm1.sgcPusherAuthentication(Sender: TObject;
AuthRequest: TsgcWSPusherRequestAuthentication;
AuthResponse: TsgcWSPusherResponseAuthentication);
begin
// For private-encrypted channels, set the shared secret
// returned by your authorization server
AuthResponse.Secret := 'your-app-secret';
AuthResponse.SharedSecret := 'base64-encoded-per-channel-key';
end;
订阅加密频道
// Subscribe to a private-encrypted channel
sgcPusher.Subscribe('my-secret-channel', pscPrivateEncryptedChannel);
// Subscribe to a private-encrypted cache channel
sgcPusher.Subscribe('my-secret-cache', pscPrivateEncryptedCacheChannel);
在加密频道上发布消息
// Client events work on private-encrypted channels just like private channels
sgcPusher.Publish('my-event', 'my-secret-channel',
pscPrivateEncryptedChannel, '{"message":"Hello encrypted!"}');
2. 新 WebSocket 事件
新增了四个事件,用于处理之前未处理的 Pusher 内部协议消息。
当相应的
pusher_internal: 消息通过 WebSocket 连接到达时,这些事件会自动触发。
| 事件属性 | 协议消息 | 描述 |
|---|---|---|
OnPusherMemberAdded |
pusher_internal:member_added |
当新用户加入存在频道时触发。提供频道名称、用户 ID 和用户信息。 |
OnPusherMemberRemoved |
pusher_internal:member_removed |
当用户离开存在频道时触发。提供频道名称、用户 ID 和用户信息。 |
OnPusherSubscriptionCount |
pusher_internal:subscription_count |
当频道的订阅数发生变化时触发。需在 Pusher 控制台中启用。 |
OnPusherCacheMiss |
pusher_internal:cache_miss |
当订阅的缓存频道没有可用缓存事件时触发。 |
OnPusherMemberAdded / OnPusherMemberRemoved
这些事件使用新的 TsgcWSPusherMemberEvent 回调类型,
以独立参数形式提供频道名称、用户 ID 和用户信息:
TsgcWSPusherMemberEvent = procedure(Sender: TObject;
Channel, UserId, UserInfo: String) of object;
procedure TForm1.sgcPusherMemberAdded(Sender: TObject;
Channel, UserId, UserInfo: String);
begin
Memo1.Lines.Add('User joined: ' + UserId + ' on ' + Channel);
if UserInfo '' then
Memo1.Lines.Add(' Info: ' + UserInfo);
end;
procedure TForm1.sgcPusherMemberRemoved(Sender: TObject;
Channel, UserId, UserInfo: String);
begin
Memo1.Lines.Add('User left: ' + UserId + ' from ' + Channel);
end;
OnPusherSubscriptionCount
使用新的 TsgcWSPusherSubscriptionCountEvent 回调类型。
此事件需要在 Pusher 控制台设置中启用订阅计数功能。
TsgcWSPusherSubscriptionCountEvent = procedure(Sender: TObject;
Channel: String; SubscriptionCount: Integer) of object;
procedure TForm1.sgcPusherSubscriptionCount(Sender: TObject;
Channel: String; SubscriptionCount: Integer);
begin
Memo1.Lines.Add(Channel + ' now has ' + IntToStr(SubscriptionCount) +
' subscribers');
end;
OnPusherCacheMiss
使用新的 TsgcWSPusherCacheMissEvent 回调类型。
当您订阅缓存频道(cache-、
private-cache-,
private-encrypted-cache- 或
presence-cache-)且没有可用缓存事件时触发。
TsgcWSPusherCacheMissEvent = procedure(Sender: TObject;
Channel: String) of object;
procedure TForm1.sgcPusherCacheMiss(Sender: TObject; Channel: String);
begin
Memo1.Lines.Add('No cached event for channel: ' + Channel);
end;
3. 新 REST API 方法
TsgcWS_API_Pusher 组件新增了两个服务器端 REST API 方法,
覆盖批量事件端点和用户连接终止。
| 方法 | Pusher 端点 | 描述 |
|---|---|---|
TriggerBatchEvents |
POST /apps/{app_id}/batch_events |
在单个 HTTP 请求中触发最多 10 个事件。每个事件可针对不同的频道。 |
TerminateUserConnections |
POST /apps/{app_id}/users/{user_id}/terminate_connections |
终止特定已认证用户的所有 WebSocket 连接。 |
TriggerBatchEvents
function TriggerBatchEvents(const aBatch: String): String;
aBatch 参数是包含
batch 事件对象数组的 JSON 字符串。每个对象必须包含
channel、
name 和
data。每批次最多 10 个事件。
var
vBatch, vResult: string;
begin
vBatch :=
'{"batch": [' +
' {"channel": "my-channel-1", "name": "my-event", "data": "{\"msg\":\"hello\"}"}' + ',' +
' {"channel": "my-channel-2", "name": "my-event", "data": "{\"msg\":\"world\"}"}' +
']}';
vResult := sgcPusher.TriggerBatchEvents(vBatch);
Memo1.Lines.Add(vResult);
end;
TerminateUserConnections
function TerminateUserConnections(const aUserId: String): String;
强制终止指定用户的所有活跃 WebSocket 连接。适用于 在所有设备上注销用户或在权限变更后撤销访问权限。 需要配置 Pusher 用户认证。
var
vResult: string;
begin
// Disconnect user "user-123" from all sessions
vResult := sgcPusher.TerminateUserConnections('user-123');
Memo1.Lines.Add(vResult);
end;
4. 更新的 REST API 方法
三个现有 REST API 方法已通过新增可选参数得到增强。由于新参数均有默认值, 现有代码完全向后兼容。
TriggerEvent
原始签名
function TriggerEvent(const aEventName, aChannel, aData: String): String;
新签名
function TriggerEvent(const aEventName, aChannel, aData: String;
const aSocketId: String = '';
const aInfo: String = ''): String;
| 参数 | 描述 |
|---|---|
aSocketId |
排除此 socket ID 不接收事件。用于防止发送方收到自己的广播。 |
aInfo |
要返回的属性逗号分隔列表。有效值:subscription_count、user_count。 |
var
vResult: string;
begin
// Trigger event, exclude the sender, and request subscription count
vResult := sgcPusher.TriggerEvent('my-event', 'my-channel',
'{"msg":"hello"}', sgcPusher.FSocket_id, 'subscription_count');
Memo1.Lines.Add(vResult);
// Response: {"channels":{"my-channel":{"subscription_count":5}}}
end;
GetChannels
原始签名
function GetChannels: String;
新签名
function GetChannels(
const aFilterByPrefix: String = '';
const aInfo: String = ''): String;
| 参数 | 描述 |
|---|---|
aFilterByPrefix |
按名称前缀过滤返回的频道。示例:presence- 仅返回存在频道。 |
aInfo |
逗号分隔的属性。有效值:user_count(仅限存在频道)、subscription_count。 |
var
vResult: string;
begin
// List all presence channels with user counts
vResult := sgcPusher.GetChannels('presence-', 'user_count');
Memo1.Lines.Add(vResult);
// Response: {"channels":{"presence-room":{"user_count":3}}}
// List all channels (no filter) - backward-compatible call
vResult := sgcPusher.GetChannels;
Memo1.Lines.Add(vResult);
end;
GetChannel
原始签名
function GetChannel(const aChannel: String): String;
新签名
function GetChannel(const aChannel: String;
const aInfo: String = ''): String;
| 参数 | 描述 |
|---|---|
aInfo |
逗号分隔的属性。有效值:subscription_count、user_count、cache。 |
var
vResult: string;
begin
// Get channel info with subscription count and user count
vResult := sgcPusher.GetChannel('presence-room',
'subscription_count,user_count');
Memo1.Lines.Add(vResult);
// Response: {"occupied":true,"subscription_count":5,"user_count":3}
// Get basic channel info - backward-compatible call
vResult := sgcPusher.GetChannel('my-channel');
Memo1.Lines.Add(vResult);
end;
5. 错误修复
此版本识别并修复了若干错误:
| 错误 | 影响 | 修复 |
|---|---|---|
Typo in DoReadEvent: 'puserh:ping' |
严重 服务器 ping 从未被识别,导致客户端错过心跳请求,可能引发服务器因不活跃而断开连接。 | 已更正为 'pusher:ping'。 |
DoSendPong null access |
高 未经空值检查访问 JSON.Node['data'].Value,若 ping 消息无数据字段可能导致访问冲突。 |
已添加空值检查;数据缺失时默认为 {}。 |
GetUsers hardcoded prefix |
高 方法始终在频道名前添加 presence-,若用户已传入完整频道名(如 presence-presence-room)则前缀会重复。 |
已移除硬编码前缀。用户现在应传入包含 presence- 前缀的完整频道名。 |
GetUsers double semicolon |
低 方法末尾存在多余的双分号 ;;。 |
已移除多余的分号。 |
GetUsers 的破坏性变更:GetUsers 方法不再
自动添加 presence- 前缀。如果您的代码仅传入频道
名称而不含前缀(如 GetUsers('my-room')),您必须将其更新为
包含完整名称:GetUsers('presence-my-room')。
6. 摘要
| 类别 | 数量 | 详情 |
|---|---|---|
| 新频道类型 | 2 | pscPrivateEncryptedChannel, pscPrivateEncryptedCacheChannel |
| 新 WebSocket 事件 | 4 | OnPusherMemberAdded, OnPusherMemberRemoved, OnPusherSubscriptionCount, OnPusherCacheMiss |
| 新 REST 方法 | 2 | TriggerBatchEvents, TerminateUserConnections |
| 更新的 REST 方法 | 3 | TriggerEvent (+socket_id, +info), GetChannels (+filter, +info), GetChannel (+info) |
| 新属性 | 1 | SharedSecret on TsgcWSPusherResponseAuthentication |
| 错误修复 | 4 | ping 拼写错误、pong 空值访问、GetUsers 前缀、双分号 |
所有更改向后兼容。新方法参数使用默认值,新事件属性
为可选项。唯一的行为变更在于
GetUsers,不再自动添加
presence- 前缀。
