- Print
- DarkLight
- PDF
WebSub Hub Nodes are Nodes that implement the Hub actor in the WebSub specification. Hubs sit between the Publisher and Subscribers. They support registration and maintenance of subscriptions to topics and the distribution of topic content updates from the Publisher to the topic's Subscribers. All content distribution is accomplished via webhooks. Any MIME type may be distributed by the Publisher.
WebSub Hubs Nodes receive echo.websub
Messages from the Publisher (which is probably another Node or Nodes in your Tenant) and route those to active subscribers based upon the Topic URL. Just like all other Nodes in EchoStream, Messages that you send to the WebSub Hub Node are guaranteed to be delivered (unless you configure deliveryRetries
> 0) and are guaranteed to be in order.
Authentication and authorization of new Subscribers is accomplished via the Api Authenticator Function that you provide to the WebSub Hub Node.
Content Distribution
WebSub Hub Nodes accept echo.websub
Messages for WebSub content distribution. The echo.websub
Message type is a JSON message and has the following attributes:
- contentBase64: The actual content that will be distributed. Must be binary in base64 encoding. Conflicts with
contentUrl
, and will not be used if that field is present. If this is present andcontentType
is not present,text/plain
is assumed as thecontentType
to send. The contents of this field will be sent as-is. - contentType: The MIME type of the content. If is not present and
contentUrl
is present, will use theContent-Type
received from thecontentUrl
if present. If it is present it will always be theContent-Type
sent to the subscriber. - contentUrl: The URL to retrive the content to send using HTTP GET. Conflicts with
contentBase64
; if both are presentcontentUrl
will be used unless the provided URL returns an error code. The body retrieved from the URL will be sent to the subscriber as-is. - topic: The topic URL that this content is for. REQUIRED
WebSub Hub Nodes are capable of distributing any Content-Type. The Content-Type being distributed should match the content type negotiated during topic discovery.
Note - While WebSub Hubs (and Webhooks in general) are normally used to distribute text-based content (e.g. - JSON, XML, Plain text), the WebSub standard itself makes no such restrictions; in fact, the standard explicitly states that the Hub must be content unaware.
Api Authenticator Function
The Api Authenticator Function that you give the WebSub Hub Node controls how the Hub responds to new subscription requests. You may provide this Python function either directly in the Webhook Node (an inline function) or by specifying the name of a Api Authenticator Function in your Tenant's Function Library.
If you do not provide an Api Authenticator Function, all subscription requests will be denied.
Api Authenticator functions are also allowed to have the async
keyword prior to their definition.
Api Authenticator functions used in WebSub Hub Nodes must conform to the following template:
def authenticator(*, context, request, **kwargs):
from typing import TYPE_CHECKING, cast
from fastapi import HTTPException
from starlette.authentication import AuthCredentials, BaseUser, SimpleUser
if TYPE_CHECKING:
from echostream_function_context import Context
from fastapi import Request
context = cast(Context, context)
request = cast(Request, request)
# TODO - Perform authentication using the context and request here
# You must either return None or return a tuple containing an AuthCredentials
# and a subclass of BaseUser. If you return None or a Base User that returns False
# from is_authenticated, then the Request will be rejected with a 403.
#
# The BaseUser subclass that you return MUST implement the identity property, as below.
#
# The AuthCredentials returned should contain one or more regular expressions that describe
# the topics that the subscriber is allowed to subscribe to. In the example below, all topics are
# authorized.
class WebSubUser(SimpleUser):
@property
def identity(self) -> str:
return self.username
return AuthCredentials([r"http[s]?://.*"])), WebSubUser("foobar")
NOTE - you must not have any Python code outside of the single function
def
statement!!
Arguments
The arguments for your api authenticator functions are all keyword arguments. An explanation of the arguments are below:
Argument | Type | Description |
---|---|---|
context | object | The Context object providing execution environment information and helper objects and methods. |
request | fastapi.Request | The Request object providing all attributes of the request as received. |
kwargs | dict | This is present specifically to future-proof your function. If, in the future, EchoStream Webhook Nodes pass additional arguments to your api authenticator function, those additional arguments will not break the call to your function. |
Return
Your processor function must return one of the following types; None
, tuple[starlette.authentication.AuthCredentials, starlette.authentication.BaseUser]
.
None
: The WebSub Hub Node will accept subscription requests from anyone but will deny all of them.tuple[starlette.authentication.AuthCredentials, starlette.authentication.BaseUser]
:AuthCredentials
: The WebSub Hub Node uses thescopes
of theAuthCredentials
to authorize subscriptions to topics. It treats thescopes
as regular expressions; it the topic URL matches any of the regular expressions inscopes
, that subscription is accepted; otherwise, the subscription will be denied.BaseUser
: The WebSub Hub Node will only accept the request if theBaseUser
instance returnsTrue
fromis_authenticated
. Otherwise it will return a403
to the client. The instance ofBaseUser
that you return must implement theidentity
property, as this will be used to identify the subscriber in a subscription.
NOTE - if you return any type other than those specified, the Webhook Node will throw an exception and cease processing.
Exceptions
You may raise a fastapi.HTTPException
from your api authenticator. The Webhook Node will reject the request and return a response to the client as dictated by the exception.
NOTE - raising
HTTPException
is a effective way to get granular in your response to the client.
Any other exception raised will result in a 500
return to the client.
Requirements
You can use any package available on PyPI in your Api Authenticator function.
Simply add the requirement to the requirements
of your WebSub Hub Node and it will be included in your Node. Thisis done using pip requirement specifiers.
For example, to include the most popular PostgreSQL database adapter for Python (psycopyg), you would put the following requirement in your Node's requirements
:
- For the latest release:
psycopg2
- Pinning the release:
psycopg2 == 2.9.3
- Ensuring a baseline release
psycopg2 >= 2.9.2
Then in your Api Authenticator function, you can use psycopg2
by importing it, as follows:
def authenticator(*, context, request, **kwargs):
# Make SURE that you import INSIDE of the function!!
import psycopg2
...
Subscription Settings
WebSub Hub Nodes support several settings that are beyond the scope of the WebSub standard. These settings allow for further control over the security, duration and retries for subscriptions to the Hub.
Name | Description | Default |
---|---|---|
defaultLeaseSeconds | The lease duration to apply to subscription requests that do not specify hub.lease_seconds | 864000 |
deliveryRetries | The number of times to attempt delivery to a subscription | Unlimited |
maxLeaseSeconds | The maximum lease duration for a subscription | 864000 |
signatureAlgorithm | The WebSub signature algorithm used by hub subscriptions when the subscription provides a hub.secret | sha1 |
subscriptionSecurity | The security requirements the hub is enforcing on subscription requests; you may enforce HTTPS callbacks, hub.secret , or both | None |