Server push
Allow your frontend to react to server events using Server Sent Events (SSE).
Info
This feature is provided by Flask-Mercure-SSE
Publishing events
Use app.sse.publish(event_name, data)
for publishing a new event. By default, anybody listening on the SSE endpoint will see these events. Add private=True
to only send to authentified clients.
current_app.sse.publish("messages", "hello world")
Data sent with the event can be a string or a json serializable object. You can send rendered component by calling components programmatically:
current_app.sse.publish("messages", current_app.components.ChatMessage(msg="hello world"))
Listening for events
Hyperflask provides some components to leverage the htmx sse extension.
<{MercureStream topic="messages"}>
{# default content #}
</{MercureStream}>
Property | Required | Type | Description | Default |
---|---|---|---|---|
topic | Yes | string | The topic name | |
private | No | bool | Whether to use an authentified url | False |
hx_swap | No | string | The swap strategy | beforeend |
type | No | string | The type of event to listen to | message |
auto_scroll | No | bool | Whether to keep the div scrolled at the bottom when receiving new items | False |
Any additional properties | Will be used as attributes of the div |
To create a div which content will be replaced on each new message, use hx_swap="innerHTML"
.
Info
Using Hyperflask components is optional and htmx sse extension or any EventSource can be used directly.
Retrieve the stream URL for an event using mercure_hub_url(event_names)
. Use mercure_authentified_hub_url(event_names)
to create authentified URLs that can receive private events.
<div hx-ext="sse" sse-connect="{{mercure_authentified_hub_url('messages')}}" sse-swap="message" hx-swap="beforeend">
</div>
Using with models
Model objects can be used as topic and/or data when publishing and subscribing. Combined with models rendering capability, this makes it easy to publish rendered objects on a stream.
When using a model class as topic, the topic will be the class name. When using a model object, the topic will be scoped to the object id.
class TodoList(db.Model):
pass
class TodoItem(db.Model):
__macro__ = "TodoItem"
todolist = TodoList()
item1 = TodoItem()
# publish the rendered item using the <{TodoItem}/> component
# on the todolist stream named "TodoList/{id}" (where id will be replaced by the list id)
current_app.sse.publish(todolist, item1)
Multiplexing a stream
Publish messages on multiple topics and set a type:
current_app.sse.publish("topic1", "data", type="topic1")
current_app.sse.publish("topic2", "data", type=True) # same effect without repeating topic in type
Tip
Add mercure_type_is_topic: true
to your config file to make it the default behavior.
Connect to multiple topics at once and distinguish messages using their type:
<{MercureStreamContext topics=["topic1", "topic2"]}>
<{MercureStream type="topic1"}>
</{MercureStream}>
<{MercureStream type="topic2"}>
</{MercureStream}>
</{MercureStreamContext}>