Skip to content
rest-rpc
Esc
navigateopen⌘Jpreview
On this page

WebSockets

Use rest-rpc with WebSockets

Usage

Contract


export const api = router({
	chat: {
		room: {
			method: "GET",
			path: "/rooms/:roomId",
			mode: "webSocket",
			pathParams: z.object({
				roomId: z.string().min(1),
			}),
			query: z.object({
				name: z.string().min(1),
			}),
			messages: {
				client: z.object({
					text: z.string().min(1),
				}),
				server: webSocketMessages("type", {
					joined: z.object({
						roomId: z.string(),
						name: z.string(),
					}),
					message: z.object({
						roomId: z.string(),
						name: z.string(),
						text: z.string(),
						sentAt: z.string(),
					}),
				}),
			},
		},
	},
});

Server


export const routes = router(api, {
	chat: {
		room({ roomId, name, context }) {
			const member = joinRoom(roomId, {
				name,
				socket: context.socket,
			});

			context.socket.send({
				type: "joined",
				message: { roomId, name },
			});

			context.socket.onMessage((message) => {
				broadcastToRoom(roomId, {
					type: "message",
					message: {
						roomId,
						name,
						text: message.text,
						sentAt: new Date().toISOString(),
					},
				});
			});

			context.socket.onClose(() => {
				leaveRoom(roomId, member);
			});
		},
	},
});

Client

const socket = client.chat.room.openConnection({
	roomId: "general",
	name: "Ada",
});

socket.onMessage((message) => {
	if (message.type === "joined") {
		console.log(`Joined ${message.message.roomId}`);
	}

	if (message.type === "message") {
		console.log(`${message.message.name}: ${message.message.text}`);
	}
});

socket.send({
	text: "Hello from rest-rpc",
});

Before Upgrade

registerRoutes(app, routes, {
	webSocket: {
		beforeUpgrade: ({ context, request }) => {
			const user = getUserFromContext(context);

			if (!user) {
				return { status: 401 };
			}

			if (!canJoinRoom(user, request.roomId)) {
				return { status: 403 };
			}

			return undefined;
		},
	},
});

Error Handling

Request validation errors use onRequestValidationError. After upgrade:

  • invalid incoming messages close the connection
  • errors thrown from the route handler or message handler close the connection
  • invalid outgoing messages throw before they are sent

Supported Adapters

Was this page helpful?