Triggers
The ballerina/websub connector supports event-driven integration as a WebSub subscriber. The websub:Listener exposes an HTTP endpoint that handles hub intent verification automatically and delivers content distribution notifications to your service callbacks.
Three components work together:
| Component | Role |
|---|---|
websub:Listener | Exposes an HTTP endpoint for the WebSub hub to send intent verification and content distribution requests. |
websub:SubscriberService | Defines callback methods invoked when subscription events or content distribution notifications are received. |
websub:ContentDistributionMessage | The payload delivered to the onEventNotification callback, containing headers, content type, and the distributed content. |
For action-based operations, see the Action Reference.
Listener
The websub:Listener establishes the connection and manages event subscriptions.
Configuration
The listener supports the following connection strategies:
| Config Type | Description |
|---|---|
ListenerConfiguration | Configuration for the WebSub subscriber listener. Extends the standard HTTP listener configuration with a graceful shutdown period. |
ListenerConfiguration fields:
| Field | Type | Default | Description |
|---|---|---|---|
host | string | "0.0.0.0" | The listener bind address. |
http1Settings | http:ListenerHttp1Settings | {} | HTTP/1.x specific settings. |
secureSocket | http:ListenerSecureSocket | () | SSL/TLS configuration for the listener. |
httpVersion | http:HttpVersion | HTTP_2_0 | HTTP protocol version. |
timeout | decimal | 120 | Request idle timeout in seconds. |
gracefulShutdownPeriod | decimal | 20 | Time in seconds to wait for unsubscription verification before shutting down. |
Initializing the listener
Using a port number:
import ballerina/websub;
listener websub:Listener websubListener = new (9090);
Using a port number with custom configuration:
import ballerina/websub;
listener websub:Listener websubListener = new (9090,
gracefulShutdownPeriod = 30
);
Using an existing HTTP listener:
import ballerina/http;
import ballerina/websub;
listener http:Listener httpListener = new (9090);
listener websub:Listener websubListener = new (httpListener);
Service
A websub:SubscriberService is a Ballerina service attached to a websub:Listener. It uses the @websub:SubscriberServiceConfig annotation to specify the target hub/topic for subscription and implements callbacks to handle subscription lifecycle events and content distribution notifications.
Callback signatures
| Function | Signature | Description |
|---|---|---|
onSubscriptionValidationDenied | remote function onSubscriptionValidationDenied(websub:SubscriptionDeniedError msg) returns websub:Acknowledgement|error? | Invoked when the hub denies the subscription request. Receives the denial reason. |
onSubscriptionVerification | remote function onSubscriptionVerification(websub:SubscriptionVerification msg) returns websub:SubscriptionVerificationSuccess|websub:SubscriptionVerificationError|error | Invoked when the hub sends a subscription intent verification challenge. Return success to confirm or error to reject. |
onUnsubscriptionVerification | remote function onUnsubscriptionVerification(websub:UnsubscriptionVerification msg) returns websub:UnsubscriptionVerificationSuccess|websub:UnsubscriptionVerificationError|error | Invoked when the hub sends an unsubscription intent verification challenge. Return success to confirm or error to reject. |
onEventNotification | remote function onEventNotification(websub:ContentDistributionMessage event) returns websub:Acknowledgement|websub:SubscriptionDeletedError|error? | Invoked when the hub distributes new content. Receives the content payload with headers and body. |
You do not need to implement all callbacks. Only implement the ones relevant to your use case. At minimum, implement onEventNotification to receive content updates.
Full usage example
import ballerina/log;
import ballerina/websub;
configurable string hubUrl = ?;
configurable string topicUrl = ?;
listener websub:Listener websubListener = new (9090);
@websub:SubscriberServiceConfig {
target: [hubUrl, topicUrl],
secret: "my-secret-key",
unsubscribeOnShutdown: true
}
service /websub on websubListener {
remote function onSubscriptionValidationDenied(
websub:SubscriptionDeniedError msg) returns websub:Acknowledgement? {
log:printError("Subscription denied: " + msg.message());
return websub:ACKNOWLEDGEMENT;
}
remote function onSubscriptionVerification(
websub:SubscriptionVerification msg)
returns websub:SubscriptionVerificationSuccess|websub:SubscriptionVerificationError {
log:printInfo("Subscription verification received for topic: " + msg.hubTopic);
if msg.hubTopic == topicUrl {
return websub:SUBSCRIPTION_VERIFICATION_SUCCESS;
}
return websub:SUBSCRIPTION_VERIFICATION_ERROR;
}
remote function onEventNotification(
websub:ContentDistributionMessage event)
returns websub:Acknowledgement|error? {
log:printInfo("Event received", contentType = event.contentType);
json|error content = event.content.ensureType();
if content is json {
log:printInfo("Content: " + content.toJsonString());
}
return websub:ACKNOWLEDGEMENT;
}
}
The target field in @websub:SubscriberServiceConfig can be either a resource URL string (the connector discovers the hub and topic automatically) or a [hubUrl, topicUrl] tuple for direct configuration. When unsubscribeOnShutdown is true, the connector sends an unsubscription request when the service stops.
Supporting types
ContentDistributionMessage
| Field | Type | Description |
|---|---|---|
headers | map<string|string[]>? | HTTP headers from the content distribution request. |
contentType | string? | The content type of the distributed content (e.g., "application/json"). |
content | map<string|string[]>|json|xml|string|byte[] | The distributed content payload. |
SubscriptionVerification
| Field | Type | Description |
|---|---|---|
hubMode | string | The hub mode (subscribe). |
hubTopic | string | The topic URL being verified. |
hubChallenge | string | The challenge string that must be echoed back to confirm the subscription. |
hubLeaseSeconds | string? | The lease duration in seconds for the subscription. |
UnsubscriptionVerification
| Field | Type | Description |
|---|---|---|
hubMode | string | The hub mode (unsubscribe). |
hubTopic | string | The topic URL being verified. |
hubChallenge | string | The challenge string that must be echoed back to confirm the unsubscription. |
hubLeaseSeconds | string? | The lease duration (may be present in the verification request). |
SubscriptionChangeRequest
| Field | Type | Description |
|---|---|---|
topic | string | The topic URL to subscribe to or unsubscribe from. |
callback | string | The callback URL for the hub to send notifications to. |
leaseSeconds | int | The requested lease period in seconds (default 0). |
secret | string | The secret for HMAC-based content verification (default empty). |
customParams | map<string>? | Additional custom parameters to include in the subscription request. |
customHeaders | map<string>? | Additional custom HTTP headers to include in the subscription request. |
SubscriptionChangeResponse
| Field | Type | Description |
|---|---|---|
hub | string | The hub URL. |
topic | string | The topic URL. |
response | http:Response | The HTTP response from the hub. |
SubscriberServiceConfiguration
| Field | Type | Description |
|---|---|---|
target | string|[string, string] | Resource URL for auto-discovery, or a [hubUrl, topicUrl] tuple for direct configuration. |
leaseSeconds | int? | Requested subscription lease period in seconds. |
callback | string? | Explicit callback URL (overrides auto-generated URL). |
secret | string? | Secret for HMAC-based authenticated content distribution. |
appendServicePath | boolean | Whether to append the service path to the callback URL (default false). |
unsubscribeOnShutdown | boolean | Whether to send an unsubscription request when the service shuts down (default false). |
customParams | map<string>? | Additional custom parameters for the subscription request. |
customHeaders | map<string>? | Additional custom HTTP headers for the subscription request. |