一个用于与 Pusher Channels HTTP API 交互的 Swift 库。
注册一个 Pusher 帐户,设置一个 Channels 应用,并使用如下所示的应用凭据。
要使用 Swift Package Manager 将库集成到您的项目中,您可以在 Xcode 中添加该库作为依赖项 – 请参阅文档。 包仓库 URL 是
https://github.com/pusher/pusher-http-swift.git
或者,您可以将该库作为依赖项添加到您的 Package.swift
文件中。 例如
// swift-tools-version:5.3
import PackageDescription
let package = Package(
name: "YourPackage",
products: [
.library(
name: "YourPackage",
targets: ["YourPackage"]),
],
dependencies: [
.package(url: "https://github.com/pusher/pusher-http-swift.git",
.upToNextMajor(from: "1.0.1")),
],
targets: [
.target(
name: "YourPackage",
dependencies: ["Pusher"]),
]
)
然后,您需要在任何希望使用该库的源文件中包含一个 import Pusher
语句。
本节介绍如何配置和使用此库,通过 Channels HTTP API 作为 Pusher Channels 应用的接口。
注意
try!
是为了简洁起见,不建议在生产应用程序中使用。使用 Pusher Channels 应用程序中的凭据来创建一个新的 Pusher
实例,该实例将作为您的 API 客户端
let pusher = Pusher(options: try! PusherClientOptions(appId: 123456,
key: "YOUR_APP_KEY",
secret: "YOUR_APP_SECRET",
encryptionMasterKey: "YOUR_BASE64_ENCODED_MASTER_KEY",
cluster: "YOUR_APP_CLUSTER"))
注意
encryptionMasterKey
的详细信息,请参见端到端加密中的讨论。要在一个或多个频道上触发事件,请使用 trigger(event:callback:)
方法。
let publicChannel = Channel(name: "my-channel", type: .public)
let publicEvent = try! Event(name: "my-event",
data: "hello world!",
channel: publicChannel)
self.pusher.trigger(event: publicEvent) { result in
switch result {
case .success(let channelSummaries):
// Inspect `channelSummaries`
case .failure(let error):
// Handle error
}
}
let publicChannelOne = Channel(name: "my-channel", type: .public)
let publicChannelTwo = Channel(name: "my-other-channel", type: .public)
let multichannelEvent = try! Event(name: "my-multichannel-event",
data: "hello world!",
channels: [publicChannelOne,
publicChannelTwo])
self.pusher.trigger(event: publicEvent) { result in
switch result {
case .success(let channelSummaries):
// Inspect `channelSummaries`
case .failure(let error):
// Handle error
}
}
也可以使用 trigger(events:callback:)
方法,通过单个 API 调用发送多个事件(在多租户集群上,每次调用最多 10 个事件)
let publicChannelOne = Channel(name: "my-channel", type: .public)
let publicChannelTwo = Channel(name: "my-other-channel", type: .public)
let eventOne = try! Event(name: "my-event",
data: "hello world!",
channel: publicChannelOne)
let eventTwo = try! Event(name: "my-other-event",
data: "hello world, again!",
channel: publicChannelTwo)
self.pusher.trigger(events: [eventOne, eventTwo]]) { result in
switch result {
case .success(let channelInfoList):
// Inspect `channelInfoList`
case .failure(let error):
// Handle error
}
}
在某些情况下,您希望阻止广播事件的客户端接收该事件。 您可以通过指定其 socketId
[href="https://pusher.com/docs/channels/server_api/excluding-event-recipients" rel="nofollow" data-turbo="false">https://pusher.com/docs/channels/server_api/excluding-event-recipients] 来实现, 触发事件时
let socketIdToExclude = "123.456"
let publicChannel = Channel(name: "my-channel", type: .public)
let excludedClientEvent = try! Event(name: "my-event",
data: "hello world!",
channel: publicChannel,
socketId: socketIdToExclude)
self.pusher.trigger(event: excludedClientEvent) { result in
switch result {
case .success(let channelSummaries):
// Inspect `channelSummaries`
case .failure(let error):
// Handle error
}
}
可以使用 Event
上的 attributeOptions
参数来获取有关已触发到的频道的信息。 这适用于两种 trigger(…)
方法
let publicChannel = Channel(name: "my-channel", type: .public)
let publicEvent = try! Event(name: "my-event",
data: "hello world!",
channel: publicChannel,
attributeOptions: [.subscriptionCount])
self.pusher.trigger(event: publicEvent) { result in
switch result {
case .success(let channelSummaries):
// Inspect `channelSummaries`
case .failure(let error):
// Handle error
}
}
注意
trigger(…)
方法是异步的。 如果您不在 GUI 应用程序中使用此方法,则可能需要使用信号量let publicChannel = Channel(name: "my-channel", type: .public)
let publicEvent = try! Event(name: "my-event",
data: "hello world!",
channel: publicChannel)
let sema = DispatchSemaphore(value: 0)
pusher.trigger(event: publicEvent) { result in
switch result {
case .success(let channelSummaries):
// Inspect `channelSummaries
case .failure(let error):
// Handle error
}
sema.signal()
}
sema.wait()
尝试订阅私有频道或在线频道的用户必须首先通过身份验证。身份验证令牌可以返回给尝试订阅的用户客户端,该客户端需要使用服务器进行身份验证。
要验证尝试订阅私有频道用户的身份,可以使用 authenticate(channel:socketId:callback:)
方法
let userSocketId = "123.456"
let privateChannel = Channel(name: "my-channel", type: .private)
self.pusher.authenticate(channel: privateChannel,
socketId: userSocketId) { result in
switch result {
case .success(let authToken):
// Inspect `authToken`
case .failure(let error):
// Handle error
}
}
要验证尝试订阅在线频道用户的身份,您必须为同一方法提供一个 userData
参数
let userData = PresenceUserAuthData(userId: "USER_ID", userInfo: ["name": "Joe Bloggs"])
let presenceChannel = Channel(name: "my-channel", type: .presence)
self.pusher.authenticate(channel: presenceChannel,
socketId: "USER_SOCKET_ID",
userData: userData) { result in
switch result {
case .success(let authToken):
// Inspect `authToken`
case .failure(let error):
// Handle error
}
}
此库提供了一种方法来验证收到的 webhook 请求是否真实且是从 Pusher 收到的。 由于 webhook 端点可供全球互联网访问,因此验证 webhook 请求是否来自 Pusher 非常重要。 有效的 webhook 包含特殊的标头,其中包含您的应用程序密钥的副本和 webhook 负载(即其正文)的 HMAC 签名
self.pusher.verifyWebhook(request: receivedWebhookRequest) { result in
switch result {
case .success(let webhook):
// Inspect `webhook`
case .failure(let error):
// Handle error
}
}
此库支持私有频道的端到端加密。 这意味着只有您和您连接的客户端才能读取您的消息。 Pusher 无法解密它们。 您可以通过以下步骤启用此功能
您应该首先设置私有频道。这涉及到在您的服务器上创建一个身份验证端点。
接下来,生成您的 32 字节主加密密钥,将其编码为 Base-64 并将其传递给 PusherClientOptions
初始化器。 这是秘密,您不应该与任何人分享,甚至包括 Pusher。
openssl rand -base64 32
let options = try! PusherClientOptions(appId: 123456,
key: "YOUR_APP_KEY",
secret: "YOUR_APP_SECRET",
encryptionMasterKey: "<MASTER KEY GENERATED BY PREVIOUS COMMAND>",
cluster: "YOUR_APP_CLUSTER")
您希望使用端到端加密的频道应为 encrypted
类型。
在您的客户端中订阅这些频道,您就完成了!您可以通过查看 https://dashboard.pusher.com/ 上的调试控制台并查看混乱的密文来验证它是否工作。
重要说明:这不会加密非 encrypted
类型的频道上的消息。
限制:您不能在调用 trigger(event:callback:)
方法时在多个频道上触发单个事件,例如
let publicChannel = Channel(name: "my-channel", type: .public)
let encryptedChannel = Channel(name: "my-other-channel", type: .encrypted)
let event = try! Event(name: "my-event",
data: "hello world!",
channels: [publicChannel, encryptedChannel])
self.pusher.trigger(event: event]) { result in
switch result {
case .success(let channelSummaries):
// Inspect `channelSummaries`
case .failure(let error):
// Handle error
}
}
理由:此库中的方法直接映射到单个 Channels HTTP API 请求。 如果我们允许在多个频道上触发单个事件(某些加密,某些未加密),则需要两个 API 请求:一个用于将事件加密到加密频道,另一个用于将事件解密到未加密频道。
可以使用该库获取有关 Channels 应用程序当前状态的信息。 这包括占用频道的状态和订阅在线频道的用户。
可以使用 channels(withFilter:attributeOptions:callback:)
方法获取 Channels 应用程序的任何占用频道列表
// Fetching all occupied channels
self.pusher.channels { result in
switch result {
case .success(let channelSummaries):
// Inspect `channelSummaries`
case .failure(let error):
// Handle error
}
}
// Fetching only occupied private channels
self.pusher.channels(withFilter: .private) { result in
switch result {
case .success(let channelSummaries):
// Inspect `channelSummaries`
case .failure(let error):
// Handle error
}
}
// Fetching all occupied presence channels (with user counts)
self.pusher.channels(withFilter: .presence,
attributeOptions: .userCount) { result in
switch result {
case .success(let channelSummaries):
// Inspect `channelSummaries`
case .failure(let error):
// Handle error
}
}
可以使用 channelInfo(for:attributeOptions:callback:)
方法获取有关 Channels 应用程序的频道的信息
// Fetch information for a public channel
let publicChannel = Channel(name: "my-channel", type: .public)
self.pusher.channelInfo(for: publicChannel) { result in
switch result {
case .success(let channelInfo):
// Inspect `channelInfo`
case .failure(let error):
// Handle error
}
}
// Fetch information for a private channel (with subscription count)
let privateChannel = Channel(name: "my-channel", type: .private)
self.pusher.channelInfo(for: privateChannel,
attributeOptions: [.subscriptionCount]) { result in
switch result {
case .success(let channelInfo):
// Inspect `channelInfo`
case .failure(let error):
// Handle error
}
}
// Fetch information for a presence channel (with user count)
let presenceChannel = Channel(name: "my-channel", type: .presence)
self.pusher.channelInfo(for: presenceChannel,
attributeOptions: [.userCount]) { result in
switch result {
case .success(let channelInfo):
// Inspect `channelInfo`
case .failure(let error):
// Handle error
}
}
注意
ChannelInfo
对象将不包含任何属性(无论是否已请求它们),并且其 isOccupied
属性将设置为 false
。可以使用 users(for:callback:)
方法获取 Channels 应用程序的在线频道的订阅用户列表
let presenceChannel = Channel(name: "my-channel", type: .presence)
self.pusher.users(for: presenceChannel) { result in
switch result {
case .success(let users):
// Inspect `users`
case .failure(let error):
// Handle error
}
}
完整的库文档可以在 API 文档中找到。
报告错误或请求新功能时,请确保使用相关的 issue 模板。 另请先检查是否存在已涵盖您的错误报告或新功能请求的开放 issue。
该库由 Pusher 拥有和维护。 最初由 Daniel Browne 创建。
它使用来自以下第三方存储库的代码
这些库的各个许可证包含在相应的 Swift 文件中。
该库是完全开源的,并根据 MIT 许可证发布。 如果您想在自己的项目中使用它,请参阅 LICENSE 了解详细信息。