Skip to main content

Crate nest_rs_ws

Crate nest_rs_ws 

Source
Expand description

WebSocket gateways for nestrs.

A #[gateway] struct with a #[messages] impl holds #[subscribe_message("event")] handlers. Messages ride a JSON envelope { "event": "...", "data": ... }. Because a WS upgrade is an HTTP GET, a gateway self-mounts on the existing HTTP transport — listing it in #[module(providers = [...])] is the entire wiring; it inherits port, CORS, TLS, and is governed by the boot-time access graph.

#[gateway(path = "/ws")]
#[use_guards(AuthGuard)]
struct ChatGateway {
    #[inject] svc: Arc<RoomService>,
}

#[messages]
impl ChatGateway {
    #[subscribe_message("message")]
    async fn on_message(&self, msg: SendMessage) -> ChatMessage { /* ... */ }
}

§Return-type contract

  • () — send nothing.
  • T — serialize as the reply on the request’s event name.
  • Result<(), E> / Result<T, E>Err(e) becomes an error frame { "event": "<event>", "data": { "error": "<Display of e>" } } and a warn!(target: "nest_rs::ws", ...) log.

Detection is syntactic on the type’s last path segment being Result: a type alias over Result is not detected and would leak the error variant on the wire. Always return Result (or std::result::Result) directly. Display for the error must be wire-safe — avoid #[error(transparent)] over an ORM/sqlx error.

§Server→client push

WsServer is the @WebSocketServer analog — a connection registry provided by WsModule. A handler reaches it by declaring a &WsClient parameter (a reference, distinguished from the owned payload). Pushes funnel through a per-connection outbox drained by a writer task, so the read loop never blocks on a slow Sink.

§Guards and lifecycle hooks

  • Connection-level: #[use_guards] on the gateway struct reuses the HTTP Guard trait and runs on the upgrade request.
  • Per-message: #[use_guards] beside a #[subscribe_message] runs the Layer System chain (global + per-message, deduped by TypeId) each time the event fires — same Guard::check_ws_message interface.

#[on_connect] / #[on_disconnect] on the #[messages] impl block are the OnGatewayConnection / OnGatewayDisconnect analogs; on_disconnect runs while the connection is still registered.

§Per-gateway namespacing

WsServer is generic over a zero-sized namespace marker (default Global). #[gateway(namespace = MyNs)] mounts against its own WsServer<MyNs> — a separate registry the macro self-provides — so two gateways isolate without sharing a registry.

§Ambient request data context

The connection loop runs in a task after the upgrade completes, so the task-locals an HTTP request installs have unwound by the time a message handler runs. The SocketContext seam captures opaque per-connection state from the post-guard upgrade request and re-installs it around each dispatch — this is how nest_rs_seaorm::ws re-binds executor + ability per message without nestrs-ws depending on the ORM or authz.

Re-exports§

pub use serde_json;
pub use tracing;
pub use poem;

Structs§

EventLayerTable
Per-gateway event-name → guard chain, built once at mount by #[messages] from the global + per-message Layer-System chain. Frozen for the rest of the process: the dispatcher just iterates.
GatewayEndpoint
The endpoint returned by gateway_endpoint. Generic over the gateway’s namespace N so it holds the gateway’s own WsServer<N>; N never escapes onto the handler surface.
Global
Default namespace marker for WsServer.
WsClient
Per-connection handle a #[subscribe_message] handler receives by declaring a &WsClient parameter — the @ConnectedSocket analog. Holds its gateway’s registry as a type-erased Registry so the handler surface stays free of the namespace parameter.
WsEnvelope
{ "event": ..., "data": ... } — the wire shape every gateway message rides.
WsModule
WsServer
Connection registry shared across every connection of a gateway — the @WebSocketServer analog. Registered as a singleton by WsModule for the Global namespace; any service can #[inject] Arc<WsServer> to push to clients in reaction to a domain event.

Enums§

WsReply
Dispatch outcome the connection loop turns into a frame (or silence).

Traits§

Gateway
Per-connection message dispatcher a gateway implements. #[messages] emits the impl: dispatch matches the event name, deserializes the payload, calls the handler (passing &WsClient if it asks for one), and wraps the return in WsReply. Never written by hand.
Registry
Object-safe face of a WsServer — the push/room surface a WsClient needs without naming the namespace. Payloads cross it pre-encoded as serde_json::Value so the trait stays object-safe.
SocketContext
WsMessageCheck
Object-safe view of [nest_rs_guards::Guard::check_ws_message] so the table can store any guard without importing the trait directly (avoids a nest-rs-ws → nest-rs-guards dep cycle).

Functions§

gateway_endpoint

Type Aliases§

BoxFuture
Captured
Opaque per-connection state captured on upgrade and handed back to every around call.
ConnId
Identifies one live connection within a WsServer. Allocated on connect; never reused within a process run.

Attribute Macros§

async_trait
gateway
#[gateway(path = "/ws")] — the @WebSocketGateway analog. Generates from_container, pub const PATH, and the inherent helpers #[messages] reads back.
messages
Bind a #[gateway] impl block’s message handlers. Each #[subscribe_message("event")] method handles { "event": "...", "data": ... }; the owned parameter is deserialized from data, the return value serialized back under the same event (() => no reply).