← Cloudflare Workers / workers / examples
Použití WebSockets API
WebSockets vám umožňují komunikovat v reálném čase s vašimi serverless funkcemi Cloudflare Workers. V tomto návodu se naučíte základy WebSockets na Cloudflare Workers, a to jak z pohledu psaní serverů WebSocket ve vašich funkcích Workers, tak z pohledu připojování k těmto serverům WebSocket a práce s nimi jako klient.
WebSockets jsou otevřená spojení udržovaná mezi klientem a origin serverem. V rámci spojení WebSocket si klient a origin mohou předávat data tam a zpět, aniž by museli znovu navazovat relace. Díky tomu je výměna dat v rámci spojení WebSocket rychlá. WebSockets se často používají pro aplikace v reálném čase, jako je živý chat nebo hraní her.
Napište server WebSocket
Servery WebSocket v Cloudflare Workers vám umožňují přijímat zprávy od klienta v reálném čase. Tento návod vám ukáže, jak nastavit server WebSocket ve Workers.
Klient může v prohlížeči vytvořit požadavek WebSocket vytvořením nové instance WebSocket, přičemž předáte URL adresu své funkce Workers:
// In client-side JavaScript, connect to your Workers function using WebSockets:
const websocket = new WebSocket(
"wss://example-websocket.signalnerve.workers.dev",
);Když příchozí požadavek WebSocket dorazí k funkci Workers, bude obsahovat Upgrade hlavičku, nastavenou na řetězcovou hodnotu websocket. Před vytvořením instance WebSocketu zkontrolujte přítomnost této hlavičky:
async function handleRequest(request) {
const upgradeHeader = request.headers.get('Upgrade');
if (!upgradeHeader || upgradeHeader !== 'websocket') {
return new Response('Expected Upgrade: websocket', { status: 426 });
}
}use worker::*;
#[event(fetch)]
async fn fetch(req: HttpRequest, _env: Env, _ctx: Context) -> Result<worker::Response> {
let upgrade_header = match req.headers().get("Upgrade") {
Some(h) => h.to_str().unwrap(),
None => "",
};
if upgrade_header != "websocket" {
return worker::Response::error("Expected Upgrade: websocket", 426);
}
}Jakmile řádně zkontrolujete Upgrade hlavičky můžete vytvořit novou instanci WebSocketPair, který obsahuje serverový a klientský WebSocket. Jeden z těchto WebSocketů by měla obsloužit funkce Workers a druhý by měl být vrácen jako součást Response hodnotou 101 stavový kód ↗, což znamená, že požadavek přepíná protokoly:
async function handleRequest(request) {
const upgradeHeader = request.headers.get('Upgrade');
if (!upgradeHeader || upgradeHeader !== 'websocket') {
return new Response('Expected Upgrade: websocket', { status: 426 });
}
const webSocketPair = new WebSocketPair();
const client = webSocketPair[0],
server = webSocketPair[1];
return new Response(null, {
status: 101,
webSocket: client,
});
}use worker::*;
#[event(fetch)]
async fn fetch(req: HttpRequest, _env: Env, _ctx: Context) -> Result<worker::Response> {
let upgrade_header = match req.headers().get("Upgrade") {
Some(h) => h.to_str().unwrap(),
None => "",
};
if upgrade_header != "websocket" {
return worker::Response::error("Expected Upgrade: websocket", 426);
}
let ws = WebSocketPair::new()?;
let client = ws.client;
let server = ws.server;
server.accept()?;
worker::Response::from_websocket(client)
} WebSocketPair konstruktor vrací objekt s 0 a 1 klíčů, z nichž každý obsahuje WebSocket instance jako svou hodnotu. Oba WebSockety z tohoto páru se běžně získávají pomocí Object.values ↗ a Destrukturalizace ES6 ↗, jak je vidět v příkladu níže.
Aby bylo možné zahájit komunikaci s client WebSocket ve vašem Workeru zavolejte accept na server WebSocket. Tím dáte runtime prostředí Workers pokyn, aby naslouchalo datům WebSocket a udrželo spojení s vaším client WebSocket:
async function handleRequest(request) {
const upgradeHeader = request.headers.get('Upgrade');
if (!upgradeHeader || upgradeHeader !== 'websocket') {
return new Response('Expected Upgrade: websocket', { status: 426 });
}
const webSocketPair = new WebSocketPair();
const [client, server] = Object.values(webSocketPair);
server.accept();
return new Response(null, {
status: 101,
webSocket: client,
});
}use worker::*;
#[event(fetch)]
async fn fetch(req: HttpRequest, _env: Env, _ctx: Context) -> Result<worker::Response> {
let upgrade_header = match req.headers().get("Upgrade") {
Some(h) => h.to_str().unwrap(),
None => "",
};
if upgrade_header != "websocket" {
return worker::Response::error("Expected Upgrade: websocket", 426);
}
let ws = WebSocketPair::new()?;
let client = ws.client;
let server = ws.server;
server.accept()?;
worker::Response::from_websocket(client)
}WebSockets vysílají řadu Události ke kterému se lze připojit pomocí addEventListener. Následující příklad se napojuje na message událost a vyvolá console.log daty z něj:
async function handleRequest(request) {
const upgradeHeader = request.headers.get('Upgrade');
if (!upgradeHeader || upgradeHeader !== 'websocket') {
return new Response('Expected Upgrade: websocket', { status: 426 });
}
const webSocketPair = new WebSocketPair();
const [client, server] = Object.values(webSocketPair);
server.accept();
server.addEventListener('message', event => {
console.log(event.data);
});
return new Response(null, {
status: 101,
webSocket: client,
});
}use futures::StreamExt;
use worker::*;
#[event(fetch)]
async fn fetch(req: HttpRequest, _env: Env, _ctx: Context) -> Result<worker::Response> {
let upgrade_header = match req.headers().get("Upgrade") {
Some(h) => h.to_str().unwrap(),
None => "",
};
if upgrade_header != "websocket" {
return worker::Response::error("Expected Upgrade: websocket", 426);
}
let ws = WebSocketPair::new()?;
let client = ws.client;
let server = ws.server;
server.accept()?;
wasm_bindgen_futures::spawn_local(async move {
let mut event_stream = server.events().expect("could not open stream");
while let Some(event) = event_stream.next().await {
match event.expect("received error in websocket") {
WebsocketEvent::Message(msg) => server.send(&msg.text()).unwrap(),
WebsocketEvent::Close(event) => console_log!("{:?}", event),
}
}
});
worker::Response::from_websocket(client)
}import { Hono } from 'hono'
import { upgradeWebSocket } from 'hono/cloudflare-workers'
const app = new Hono()
app.get(
'*',
upgradeWebSocket((c) => {
return {
onMessage(event, ws) {
console.log('Received message from client:', event.data)
ws.send(`Echo: ${event.data}`)
},
onClose: () => {
console.log('WebSocket closed:', event)
},
onError: () => {
console.error('WebSocket error:', event)
},
}
})
)
export default app;Připojte se k serveru WebSocket z klienta
Psaní klientů WebSocket, kteří komunikují s vaší funkcí Workers, je dvoukrokový proces: nejprve vytvoříte instanci WebSocket a poté k ní připojíte posluchače událostí:
const websocket = new WebSocket(
"wss://websocket-example.signalnerve.workers.dev",
);
websocket.addEventListener("message", (event) => {
console.log("Message received from server");
console.log(event.data);
});Klienti WebSocket mohou odesílat zprávy zpět na server pomocí send funkce:
websocket.send("MESSAGE");Jakmile je interakce přes WebSocket dokončena, klient může spojení ukončit pomocí close:
websocket.close();Příklad z praxe najdete v websocket-template ↗ abyste začali pracovat s WebSockets.
Napište klienta WebSocket
Cloudflare Workers podporuje new WebSocket(url) konstruktor. Worker může navázat WebSocket připojení ke vzdálenému serveru stejným způsobem, jaký je popsán výše u klientské implementace.
Cloudflare navíc podporuje navazování připojení WebSocket odesláním požadavku fetch na URL adresu s Upgrade hlavičku nastavenou.
async function websocket(url) {
// Make a fetch request including `Upgrade: websocket` header.
// The Workers Runtime will automatically handle other requirements
// of the WebSocket protocol, like the Sec-WebSocket-Key header.
let resp = await fetch(url, {
headers: {
Upgrade: "websocket",
},
});
// If the WebSocket handshake completed successfully, then the
// response has a `webSocket` property.
let ws = resp.webSocket;
if (!ws) {
throw new Error("server didn't accept WebSocket");
}
// Call accept() to indicate that you'll be handling the socket here
// in JavaScript, as opposed to returning it on to a client.
// You can pass { allowHalfOpen: true } if you need to coordinate
// the close handshake manually (for example, when proxying).
ws.accept();
// Now you can send and receive messages like before.
ws.send("hello");
ws.addEventListener("message", (msg) => {
console.log(msg.data);
});
}Chování WebSocket při uzavření
S web_socket_auto_reply_to_close příznak kompatibility (ve výchozím nastavení povolen u dat kompatibility od 2026-04-07), běhové prostředí Workers automaticky odpovídá na příchozí rámce Close a přechází readyState na CLOSED před vyvoláním close událost. Nemusíte volat close() ve vašem close obslužnou rutinu události, ale je to bezpečné (volání se tiše ignoruje).
Pokud potřebujete chování s částečně otevřeným spojením (half-open), například pro proxy WebSocketu, předejte { allowHalfOpen: true } na accept(). Vezměte na vědomí, že new WebSocket(url) po nabytí účinnosti tohoto příznaku vždy automaticky odpovídá. Pokud chcete pro klientský WebSocket dosáhnout chování half-open, použijte fetch()-ový vzor uvedený výše a zavolat ws.accept({ allowHalfOpen: true }).
Podrobnosti uvádí Chování WebSocket při uzavření.
Komprese WebSocket
Cloudflare Workers podporuje kompresi WebSocket. Více informací najdete v Komprese WebSocket s dalšími informacemi.