Swift
Use the Swift HTTP server SDK to publish events, authenticate channels, validate state, and manage push.
Install
Install through Swift Package Manager from the Sockudo HTTP Swift mirror. SwiftPM resolves this from
the v2.1.0 Git tag and the mirror repository's root Package.swift manifest:
.package(url: "https://github.com/sockudo/sockudo-http-swift", from: "2.1.0").product(name: "Sockudo", package: "sockudo-http-swift")The package manifest supports Swift 5.3+, iOS 13+, macOS 10.15+, tvOS 13+, and watchOS
6+. It also exports a Pusher compatibility product for existing integrations;
new code should use Sockudo.
Configure
import Sockudo
let sockudo = Sockudo(options: try SockudoClientOptions(
appId: 123456,
key: "app-key",
secret: "app-secret",
host: "127.0.0.1",
port: 6001,
useTLS: false
))useTLS defaults to true. Keep it enabled in production and use an HTTPS API
hostname. Construct the client once in service/application state and reuse it.
Initializers validate options and throw; propagate or handle those errors
instead of using try!.
Publish
let event = try Event(
name: "order.created",
data: ["id": "ord_123"],
channel: Channel(name: "orders", type: .public),
idempotencyKey: "order-created-ord_123"
)
sockudo.trigger(event: event) { result in
switch result {
case .success(let summaries):
print(summaries)
case .failure(let error):
print(error)
}
}Publish to multiple channels or batch independent events:
let multi = try Event(
name: "order.updated",
data: ["id": "ord_123", "status": "paid"],
channels: [
Channel(name: "tenant-42:orders", type: .public),
Channel(name: "user-7:orders", type: .public),
],
idempotencyKey: "order-paid:ord_123:v3"
)
let created = try Event(
name: "order.created",
data: ["id": "ord_124"],
channel: Channel(name: "orders", type: .public)
)
let paid = try Event(
name: "order.paid",
data: ["id": "ord_124"],
channel: Channel(name: "orders", type: .public)
)
sockudo.trigger(event: multi) { result in
handlePublishResult(result)
}
sockudo.trigger(events: [created, paid]) { result in
handlePublishResult(result)
}Use an event's socketId to exclude the originating connection. Batches accept
up to 10 events. Any publish that may be retried needs a stable
business-derived idempotency key.
Auth
let privateChannel = Channel(name: "orders", type: .private)
sockudo.authenticate(channel: privateChannel, socketId: "123.456") { result in
print(result)
}
let userData = PresenceUserAuthData(userId: "user-42", userInfo: ["name": "Ada"])
let presenceChannel = Channel(name: "lobby", type: .presence)
sockudo.authenticate(channel: presenceChannel, socketId: "123.456", userData: userData) { result in
print(result)
}The SDK signs after your handler authenticates the session and authorizes the
exact channel. Derive presence identity from trusted application state. Use
authenticateUser for user-targeted events.
Webhooks
Pass the original request to verifyWebhook before processing its body:
sockudo.verifyWebhook(request: receivedRequest) { result in
switch result {
case .success(let webhook):
enqueue(events: webhook.events)
case .failure:
rejectWebhook()
}
}Do not deserialize, normalize, or log the raw body before signature verification. Make downstream processing idempotent.
State and history
sockudo.channels(
withFilter: .presence,
attributeOptions: .userCount
) { result in
handleChannels(result)
}
let orders = Channel(name: "orders", type: .public)
sockudo.history(
for: orders,
options: .init(limit: 50, direction: "newest_first")
) { result in
handleHistory(result)
}
let presence = Channel(name: "lobby", type: .presence)
sockudo.presenceSnapshot(
for: presence,
options: .init(atSerial: 4)
) { result in
handleSnapshot(result)
}Current state is an operational snapshot. Bound history pages and pass opaque cursors back unchanged.
End-to-end encrypted channels
Pass a base64-encoded 32-byte encryptionMasterKey in
SockudoClientOptions, then use a channel with type .encrypted. The SDK
encrypts payloads and derives the auth shared secret. A single event cannot mix
encrypted and unencrypted channels. Keep the master key in a secret manager
and continue to use TLS.
User connection management
sockudo.terminateUserConnections(userId: "user-42") { result in
handleUserControl(result)
}
sockudo.forceReconnectUser(userId: "user-42") { result in
handleUserControl(result)
}Terminate for immediate revocation; force reconnect when the user should obtain refreshed auth or routing state.
Push notifications
sockudo.activateDevice(body: [
"deviceId": "ios-device-1",
"clientId": "user-42",
"platform": "apns",
"providerToken": "provider-token",
]) { result in
print(result)
}
sockudo.upsertChannelPushSubscription(body: [
"deviceId": "ios-device-1",
"clientId": "user-42",
"channel": "orders",
]) { result in
print(result)
}
sockudo.publishPush(request: [
"recipients": [["type": "channel", "channel": "orders"]],
"payload": [
"title": "Order updated",
"body": "Order ord_123 is packed",
],
"idempotency_key": "push-order-ord_123-packed",
]) { result in
print(result)
}Use Swift server SDKs in trusted services, not inside untrusted client apps with app secrets.
Errors, concurrency, and production guidance
Every asynchronous operation completes with Result. Handle both cases and
avoid force-unwrapping or try! in production. Retry only transient transport
errors, 429, and suitable server responses with bounded backoff. Retried
publishes must retain their original idempotency key.
- Reuse the configured client and its URL session.
- Keep the SDK operation deadline below the enclosing request or job deadline.
- Dispatch completion work to the appropriate actor or queue for your application.
- Keep credentials, signed URLs, raw webhooks, event data, and provider tokens out of logs.
- Test duplicate attempts, key rotation, webhook retries, and graceful service shutdown.