[{"data":1,"prerenderedAt":1475},["ShallowReactive",2],{"navigation":3,"-guide-advanced-websocket":193,"-guide-advanced-websocket-surround":1471},[4,91,138,170,177],{"title":5,"path":6,"stem":7,"children":8,"icon":90},"Guide","/guide","1.guide/0.index",[9,12,53,69],{"title":10,"path":6,"stem":7,"icon":11},"Getting Started","pixel:play",{"title":5,"icon":13,"path":14,"stem":15,"children":16,"page":52},"ph:book-open-duotone","/guide/basics","1.guide/1.basics",[17,22,27,32,37,42,47],{"title":18,"path":19,"stem":20,"icon":21},"Request Lifecycle","/guide/basics/lifecycle","1.guide/1.basics/1.lifecycle","icon-park-outline:handle-round",{"title":23,"path":24,"stem":25,"icon":26},"Routing","/guide/basics/routing","1.guide/1.basics/2.routing","solar:routing-bold",{"title":28,"path":29,"stem":30,"icon":31},"Middleware","/guide/basics/middleware","1.guide/1.basics/3.middleware","mdi:middleware-outline",{"title":33,"path":34,"stem":35,"icon":36},"Event Handlers","/guide/basics/handler","1.guide/1.basics/4.handler","mdi:function",{"title":38,"path":39,"stem":40,"icon":41},"Sending Response","/guide/basics/response","1.guide/1.basics/5.response","tabler:json",{"title":43,"path":44,"stem":45,"icon":46},"Error Handling","/guide/basics/error","1.guide/1.basics/6.error","tabler:error-404",{"title":48,"path":49,"stem":50,"icon":51},"Nested Apps","/guide/basics/nested-apps","1.guide/1.basics/7.nested-apps","material-symbols-light:layers-outline",false,{"title":54,"icon":55,"path":56,"stem":57,"children":58,"page":52},"API","material-symbols-light:api-rounded","/guide/api","1.guide/900.api",[59,64],{"title":60,"path":61,"stem":62,"icon":63},"H3","/guide/api/h3","1.guide/900.api/1.h3","material-symbols:bolt-rounded",{"title":65,"path":66,"stem":67,"icon":68},"H3Event","/guide/api/h3event","1.guide/900.api/2.h3event","material-symbols:data-object-rounded",{"title":70,"icon":71,"path":72,"stem":73,"children":74,"page":52},"Advanced","hugeicons:more-01","/guide/advanced","1.guide/901.advanced",[75,80,85],{"title":76,"path":77,"stem":78,"icon":79},"Plugins","/guide/advanced/plugins","1.guide/901.advanced/1.plugins","clarity:plugin-line",{"title":81,"path":82,"stem":83,"icon":84},"WebSockets","/guide/advanced/websocket","1.guide/901.advanced/2.websocket","hugeicons:live-streaming-02",{"title":86,"path":87,"stem":88,"icon":89},"Nightly Builds","/guide/advanced/nightly","1.guide/901.advanced/9.nightly","game-icons:barn-owl","i-ph:book-open-duotone",{"title":92,"path":93,"stem":94,"children":95,"icon":97},"Utils","/utils","2.utils/0.index",[96,98,103,108,113,118,123,128,133],{"title":92,"path":93,"stem":94,"icon":97},"ph:function-bold",{"title":99,"path":100,"stem":101,"icon":102},"Request","/utils/request","2.utils/1.request","material-symbols-light:input",{"title":104,"path":105,"stem":106,"icon":107},"Response","/utils/response","2.utils/2.response","material-symbols-light:output",{"title":109,"path":110,"stem":111,"icon":112},"Cookie","/utils/cookie","2.utils/3.cookie","material-symbols:cookie-outline",{"title":114,"path":115,"stem":116,"icon":117},"Security","/utils/security","2.utils/4.security","wpf:key-security",{"title":119,"path":120,"stem":121,"icon":122},"Proxy","/utils/proxy","2.utils/5.proxy","arcticons:super-proxy",{"title":124,"path":125,"stem":126,"icon":127},"MCP","/utils/mcp","2.utils/6.mcp","material-symbols:swap-calls",{"title":129,"path":130,"stem":131,"icon":132},"More utils","/utils/more","2.utils/9.more","mingcute:plus-line",{"title":134,"path":135,"stem":136,"icon":137},"Community","/utils/community","2.utils/99.community","lets-icons:external",{"title":139,"path":140,"stem":141,"children":142,"icon":144},"Examples","/examples","4.examples/0.index",[143,145,150,154,158,162,166],{"title":139,"path":140,"stem":141,"icon":144},"ph:code",{"title":146,"path":147,"stem":148,"icon":149},"Cookies","/examples/handle-cookie","4.examples/handle-cookie","ph:arrow-right",{"title":151,"path":152,"stem":153,"icon":149},"HTTP QUERY Method","/examples/handle-query","4.examples/handle-query",{"title":155,"path":156,"stem":157,"icon":149},"Sessions","/examples/handle-session","4.examples/handle-session",{"title":159,"path":160,"stem":161,"icon":149},"Static Assets","/examples/serve-static-assets","4.examples/serve-static-assets",{"title":163,"path":164,"stem":165,"icon":149},"Stream Response","/examples/stream-response","4.examples/stream-response",{"title":167,"path":168,"stem":169,"icon":149},"Validate Data","/examples/validate-data","4.examples/validate-data",{"title":171,"path":172,"stem":173,"children":174,"icon":176},"Migration","/migration","5.migration/0.index",[175],{"title":171,"path":172,"stem":173,"icon":176},"icons8:up-round",{"title":178,"path":179,"stem":180,"children":181},"Blog","/blog","99.blog",[182,185,189],{"title":178,"path":179,"stem":183,"icon":184},"99.blog/index","i-lucide-file-text",{"title":186,"path":187,"stem":188,"icon":184},"H3 1.8 - Towards the Edge of the Web","/blog/v1.8","99.blog/1.v1.8",{"title":190,"path":191,"stem":192,"icon":184},"H3 v2 beta","/blog/v2-beta","99.blog/2.v2-beta",{"id":194,"title":81,"body":195,"description":1465,"extension":1466,"meta":1467,"navigation":1468,"path":82,"seo":1469,"stem":83,"__hash__":1470},"content/1.guide/901.advanced/2.websocket.md",{"type":196,"value":197,"toc":1457,"icon":84},"minimark",[198,210,215,223,230,378,398,404,1108,1113,1120,1126,1205,1209,1217,1224,1228,1453],[199,200,201,202,209],"p",{},"You can add cross platform WebSocket support to H3 servers using ",[203,204,208],"a",{"href":205,"rel":206},"https://crossws.h3.dev/",[207],"nofollow","🔌 CrossWS",".",[211,212,214],"h2",{"id":213},"usage","Usage",[199,216,217,218,222],{},"WebSocket handlers can be defined using the ",[219,220,221],"code",{},"defineWebSocketHandler()"," utility and registered to any route like event handlers.",[199,224,225,226,229],{},"You need to register CrossWS as a server plugin in the ",[219,227,228],{},"serve"," function. The plugin resolves the correct hooks from your matched route automatically.",[231,232,237],"pre",{"className":233,"code":234,"language":235,"meta":236,"style":236},"language-js shiki shiki-themes github-light github-dark github-dark","import { H3, serve, defineWebSocketHandler } from \"h3\";\n\nimport { plugin as ws } from \"crossws/server\";\n\nconst app = new H3();\n\napp.get(\"/_ws\", defineWebSocketHandler({ message: console.log }));\n\nserve(app, {\n  plugins: [ws()],\n});\n","js","",[219,238,239,262,269,290,295,318,323,347,352,360,372],{"__ignoreMap":236},[240,241,244,248,252,255,259],"span",{"class":242,"line":243},"line",1,[240,245,247],{"class":246},"so5gQ","import",[240,249,251],{"class":250},"slsVL"," { H3, serve, defineWebSocketHandler } ",[240,253,254],{"class":246},"from",[240,256,258],{"class":257},"sfrk1"," \"h3\"",[240,260,261],{"class":250},";\n",[240,263,265],{"class":242,"line":264},2,[240,266,268],{"emptyLinePlaceholder":267},true,"\n",[240,270,272,274,277,280,283,285,288],{"class":242,"line":271},3,[240,273,247],{"class":246},[240,275,276],{"class":250}," { plugin ",[240,278,279],{"class":246},"as",[240,281,282],{"class":250}," ws } ",[240,284,254],{"class":246},[240,286,287],{"class":257}," \"crossws/server\"",[240,289,261],{"class":250},[240,291,293],{"class":242,"line":292},4,[240,294,268],{"emptyLinePlaceholder":267},[240,296,298,301,305,308,311,315],{"class":242,"line":297},5,[240,299,300],{"class":246},"const",[240,302,304],{"class":303},"suiK_"," app",[240,306,307],{"class":246}," =",[240,309,310],{"class":246}," new",[240,312,314],{"class":313},"shcOC"," H3",[240,316,317],{"class":250},"();\n",[240,319,321],{"class":242,"line":320},6,[240,322,268],{"emptyLinePlaceholder":267},[240,324,326,329,332,335,338,341,344],{"class":242,"line":325},7,[240,327,328],{"class":250},"app.",[240,330,331],{"class":313},"get",[240,333,334],{"class":250},"(",[240,336,337],{"class":257},"\"/_ws\"",[240,339,340],{"class":250},", ",[240,342,343],{"class":313},"defineWebSocketHandler",[240,345,346],{"class":250},"({ message: console.log }));\n",[240,348,350],{"class":242,"line":349},8,[240,351,268],{"emptyLinePlaceholder":267},[240,353,355,357],{"class":242,"line":354},9,[240,356,228],{"class":313},[240,358,359],{"class":250},"(app, {\n",[240,361,363,366,369],{"class":242,"line":362},10,[240,364,365],{"class":250},"  plugins: [",[240,367,368],{"class":313},"ws",[240,370,371],{"class":250},"()],\n",[240,373,375],{"class":242,"line":374},11,[240,376,377],{"class":250},"});\n",[379,380,381],"note",{},[199,382,383,384,387,388,391,392,395,396,209],{},"\nPassing a custom ",[219,385,386],{},"resolve"," to ",[219,389,390],{},"ws()"," is only needed to resolve hooks yourself (for example without invoking the app). By default, CrossWS calls the app's ",[219,393,394],{},"fetch"," handler and reads the hooks attached by ",[219,397,221],{},[199,399,400],{},[401,402,403],"strong",{},"Full example:",[231,405,408],{"className":233,"code":406,"filename":407,"language":235,"meta":236,"style":236},"import { H3, serve, html, defineWebSocketHandler } from \"h3\";\nimport { plugin as ws } from \"crossws/server\";\n\nexport const app = new H3();\n\n// A minimal self-contained WebSocket playground served for plain HTTP requests.\nconst playground = html`\u003C!doctype html>\n  \u003Ctitle>H3 WebSocket Playground\u003C/title>\n  \u003Ch1>H3 WebSocket Playground\u003C/h1>\n  \u003Cform id=\"form\">\n    \u003Cinput id=\"input\" placeholder=\"Type a message...\" autocomplete=\"off\" autofocus />\n    \u003Cbutton type=\"submit\">Send\u003C/button>\n  \u003C/form>\n  \u003Cdiv id=\"log\">\u003C/div>\n  \u003Cscript type=\"module\">\n    const log = (msg) => {\n      const line = document.createElement(\"div\");\n      line.textContent = msg;\n      document.getElementById(\"log\").append(line);\n    };\n    const url = location.href.replace(/^http/, \"ws\");\n    const ws = new WebSocket(url);\n    ws.addEventListener(\"open\", () => log(\"[open] connected to \" + url));\n    ws.addEventListener(\"message\", (e) => log(\"[message] \" + e.data));\n    ws.addEventListener(\"close\", () => log(\"[close] disconnected\"));\n    document.getElementById(\"form\").addEventListener(\"submit\", (e) => {\n      e.preventDefault();\n      const input = document.getElementById(\"input\");\n      ws.send(input.value);\n      input.value = \"\";\n    });\n  \u003C/script>`;\n\n// A single route serves both the playground page (plain HTTP) and the\n// WebSocket endpoint (upgrade requests). The page connects back to itself.\napp.get(\n  \"/\",\n  defineWebSocketHandler(\n    {\n      open(peer) {\n        console.log(\"[open]\", peer);\n\n        // Send welcome to the new client\n        peer.send(\"Welcome to the server!\");\n\n        // Join new client to the \"chat\" channel\n        peer.subscribe(\"chat\");\n\n        // Notify every other connected client\n        peer.publish(\"chat\", `[system] ${peer} joined!`);\n      },\n\n      message(peer, message) {\n        console.log(\"[message]\", peer);\n\n        if (message.text() === \"ping\") {\n          // Reply to the client with a ping response\n          peer.send(\"pong\");\n          return;\n        }\n\n        // The server re-broadcasts incoming messages to everyone\n        peer.publish(\"chat\", `[${peer}] ${message}`);\n\n        // Echo the message back to the sender\n        peer.send(message);\n      },\n\n      close(peer) {\n        console.log(\"[close]\", peer);\n        peer.publish(\"chat\", `[system] ${peer} has left the chat!`);\n        peer.unsubscribe(\"chat\");\n      },\n    },\n    // Non-upgrade requests get the playground page.\n    () => playground,\n  ),\n);\n\nserve(app, {\n  plugins: [ws()],\n});\n","websocket.mjs",[219,409,410,423,439,443,461,465,471,486,491,496,501,506,512,518,524,530,536,542,548,554,560,566,572,578,584,590,596,602,608,614,620,626,634,639,645,651,661,670,678,684,699,716,721,727,744,749,755,770,775,781,805,811,816,833,847,852,875,881,896,904,910,915,921,949,954,960,970,975,980,992,1006,1028,1042,1047,1053,1059,1071,1077,1082,1087,1094,1103],{"__ignoreMap":236},[240,411,412,414,417,419,421],{"class":242,"line":243},[240,413,247],{"class":246},[240,415,416],{"class":250}," { H3, serve, html, defineWebSocketHandler } ",[240,418,254],{"class":246},[240,420,258],{"class":257},[240,422,261],{"class":250},[240,424,425,427,429,431,433,435,437],{"class":242,"line":264},[240,426,247],{"class":246},[240,428,276],{"class":250},[240,430,279],{"class":246},[240,432,282],{"class":250},[240,434,254],{"class":246},[240,436,287],{"class":257},[240,438,261],{"class":250},[240,440,441],{"class":242,"line":271},[240,442,268],{"emptyLinePlaceholder":267},[240,444,445,448,451,453,455,457,459],{"class":242,"line":292},[240,446,447],{"class":246},"export",[240,449,450],{"class":246}," const",[240,452,304],{"class":303},[240,454,307],{"class":246},[240,456,310],{"class":246},[240,458,314],{"class":313},[240,460,317],{"class":250},[240,462,463],{"class":242,"line":297},[240,464,268],{"emptyLinePlaceholder":267},[240,466,467],{"class":242,"line":320},[240,468,470],{"class":469},"sCsY4","// A minimal self-contained WebSocket playground served for plain HTTP requests.\n",[240,472,473,475,478,480,483],{"class":242,"line":325},[240,474,300],{"class":246},[240,476,477],{"class":303}," playground",[240,479,307],{"class":246},[240,481,482],{"class":313}," html",[240,484,485],{"class":257},"`\u003C!doctype html>\n",[240,487,488],{"class":242,"line":349},[240,489,490],{"class":257},"  \u003Ctitle>H3 WebSocket Playground\u003C/title>\n",[240,492,493],{"class":242,"line":354},[240,494,495],{"class":257},"  \u003Ch1>H3 WebSocket Playground\u003C/h1>\n",[240,497,498],{"class":242,"line":362},[240,499,500],{"class":257},"  \u003Cform id=\"form\">\n",[240,502,503],{"class":242,"line":374},[240,504,505],{"class":257},"    \u003Cinput id=\"input\" placeholder=\"Type a message...\" autocomplete=\"off\" autofocus />\n",[240,507,509],{"class":242,"line":508},12,[240,510,511],{"class":257},"    \u003Cbutton type=\"submit\">Send\u003C/button>\n",[240,513,515],{"class":242,"line":514},13,[240,516,517],{"class":257},"  \u003C/form>\n",[240,519,521],{"class":242,"line":520},14,[240,522,523],{"class":257},"  \u003Cdiv id=\"log\">\u003C/div>\n",[240,525,527],{"class":242,"line":526},15,[240,528,529],{"class":257},"  \u003Cscript type=\"module\">\n",[240,531,533],{"class":242,"line":532},16,[240,534,535],{"class":257},"    const log = (msg) => {\n",[240,537,539],{"class":242,"line":538},17,[240,540,541],{"class":257},"      const line = document.createElement(\"div\");\n",[240,543,545],{"class":242,"line":544},18,[240,546,547],{"class":257},"      line.textContent = msg;\n",[240,549,551],{"class":242,"line":550},19,[240,552,553],{"class":257},"      document.getElementById(\"log\").append(line);\n",[240,555,557],{"class":242,"line":556},20,[240,558,559],{"class":257},"    };\n",[240,561,563],{"class":242,"line":562},21,[240,564,565],{"class":257},"    const url = location.href.replace(/^http/, \"ws\");\n",[240,567,569],{"class":242,"line":568},22,[240,570,571],{"class":257},"    const ws = new WebSocket(url);\n",[240,573,575],{"class":242,"line":574},23,[240,576,577],{"class":257},"    ws.addEventListener(\"open\", () => log(\"[open] connected to \" + url));\n",[240,579,581],{"class":242,"line":580},24,[240,582,583],{"class":257},"    ws.addEventListener(\"message\", (e) => log(\"[message] \" + e.data));\n",[240,585,587],{"class":242,"line":586},25,[240,588,589],{"class":257},"    ws.addEventListener(\"close\", () => log(\"[close] disconnected\"));\n",[240,591,593],{"class":242,"line":592},26,[240,594,595],{"class":257},"    document.getElementById(\"form\").addEventListener(\"submit\", (e) => {\n",[240,597,599],{"class":242,"line":598},27,[240,600,601],{"class":257},"      e.preventDefault();\n",[240,603,605],{"class":242,"line":604},28,[240,606,607],{"class":257},"      const input = document.getElementById(\"input\");\n",[240,609,611],{"class":242,"line":610},29,[240,612,613],{"class":257},"      ws.send(input.value);\n",[240,615,617],{"class":242,"line":616},30,[240,618,619],{"class":257},"      input.value = \"\";\n",[240,621,623],{"class":242,"line":622},31,[240,624,625],{"class":257},"    });\n",[240,627,629,632],{"class":242,"line":628},32,[240,630,631],{"class":257},"  \u003C/script>`",[240,633,261],{"class":250},[240,635,637],{"class":242,"line":636},33,[240,638,268],{"emptyLinePlaceholder":267},[240,640,642],{"class":242,"line":641},34,[240,643,644],{"class":469},"// A single route serves both the playground page (plain HTTP) and the\n",[240,646,648],{"class":242,"line":647},35,[240,649,650],{"class":469},"// WebSocket endpoint (upgrade requests). The page connects back to itself.\n",[240,652,654,656,658],{"class":242,"line":653},36,[240,655,328],{"class":250},[240,657,331],{"class":313},[240,659,660],{"class":250},"(\n",[240,662,664,667],{"class":242,"line":663},37,[240,665,666],{"class":257},"  \"/\"",[240,668,669],{"class":250},",\n",[240,671,673,676],{"class":242,"line":672},38,[240,674,675],{"class":313},"  defineWebSocketHandler",[240,677,660],{"class":250},[240,679,681],{"class":242,"line":680},39,[240,682,683],{"class":250},"    {\n",[240,685,687,690,692,696],{"class":242,"line":686},40,[240,688,689],{"class":313},"      open",[240,691,334],{"class":250},[240,693,695],{"class":694},"sQHwn","peer",[240,697,698],{"class":250},") {\n",[240,700,702,705,708,710,713],{"class":242,"line":701},41,[240,703,704],{"class":250},"        console.",[240,706,707],{"class":313},"log",[240,709,334],{"class":250},[240,711,712],{"class":257},"\"[open]\"",[240,714,715],{"class":250},", peer);\n",[240,717,719],{"class":242,"line":718},42,[240,720,268],{"emptyLinePlaceholder":267},[240,722,724],{"class":242,"line":723},43,[240,725,726],{"class":469},"        // Send welcome to the new client\n",[240,728,730,733,736,738,741],{"class":242,"line":729},44,[240,731,732],{"class":250},"        peer.",[240,734,735],{"class":313},"send",[240,737,334],{"class":250},[240,739,740],{"class":257},"\"Welcome to the server!\"",[240,742,743],{"class":250},");\n",[240,745,747],{"class":242,"line":746},45,[240,748,268],{"emptyLinePlaceholder":267},[240,750,752],{"class":242,"line":751},46,[240,753,754],{"class":469},"        // Join new client to the \"chat\" channel\n",[240,756,758,760,763,765,768],{"class":242,"line":757},47,[240,759,732],{"class":250},[240,761,762],{"class":313},"subscribe",[240,764,334],{"class":250},[240,766,767],{"class":257},"\"chat\"",[240,769,743],{"class":250},[240,771,773],{"class":242,"line":772},48,[240,774,268],{"emptyLinePlaceholder":267},[240,776,778],{"class":242,"line":777},49,[240,779,780],{"class":469},"        // Notify every other connected client\n",[240,782,784,786,789,791,793,795,798,800,803],{"class":242,"line":783},50,[240,785,732],{"class":250},[240,787,788],{"class":313},"publish",[240,790,334],{"class":250},[240,792,767],{"class":257},[240,794,340],{"class":250},[240,796,797],{"class":257},"`[system] ${",[240,799,695],{"class":250},[240,801,802],{"class":257},"} joined!`",[240,804,743],{"class":250},[240,806,808],{"class":242,"line":807},51,[240,809,810],{"class":250},"      },\n",[240,812,814],{"class":242,"line":813},52,[240,815,268],{"emptyLinePlaceholder":267},[240,817,819,822,824,826,828,831],{"class":242,"line":818},53,[240,820,821],{"class":313},"      message",[240,823,334],{"class":250},[240,825,695],{"class":694},[240,827,340],{"class":250},[240,829,830],{"class":694},"message",[240,832,698],{"class":250},[240,834,836,838,840,842,845],{"class":242,"line":835},54,[240,837,704],{"class":250},[240,839,707],{"class":313},[240,841,334],{"class":250},[240,843,844],{"class":257},"\"[message]\"",[240,846,715],{"class":250},[240,848,850],{"class":242,"line":849},55,[240,851,268],{"emptyLinePlaceholder":267},[240,853,855,858,861,864,867,870,873],{"class":242,"line":854},56,[240,856,857],{"class":246},"        if",[240,859,860],{"class":250}," (message.",[240,862,863],{"class":313},"text",[240,865,866],{"class":250},"() ",[240,868,869],{"class":246},"===",[240,871,872],{"class":257}," \"ping\"",[240,874,698],{"class":250},[240,876,878],{"class":242,"line":877},57,[240,879,880],{"class":469},"          // Reply to the client with a ping response\n",[240,882,884,887,889,891,894],{"class":242,"line":883},58,[240,885,886],{"class":250},"          peer.",[240,888,735],{"class":313},[240,890,334],{"class":250},[240,892,893],{"class":257},"\"pong\"",[240,895,743],{"class":250},[240,897,899,902],{"class":242,"line":898},59,[240,900,901],{"class":246},"          return",[240,903,261],{"class":250},[240,905,907],{"class":242,"line":906},60,[240,908,909],{"class":250},"        }\n",[240,911,913],{"class":242,"line":912},61,[240,914,268],{"emptyLinePlaceholder":267},[240,916,918],{"class":242,"line":917},62,[240,919,920],{"class":469},"        // The server re-broadcasts incoming messages to everyone\n",[240,922,924,926,928,930,932,934,937,939,942,944,947],{"class":242,"line":923},63,[240,925,732],{"class":250},[240,927,788],{"class":313},[240,929,334],{"class":250},[240,931,767],{"class":257},[240,933,340],{"class":250},[240,935,936],{"class":257},"`[${",[240,938,695],{"class":250},[240,940,941],{"class":257},"}] ${",[240,943,830],{"class":250},[240,945,946],{"class":257},"}`",[240,948,743],{"class":250},[240,950,952],{"class":242,"line":951},64,[240,953,268],{"emptyLinePlaceholder":267},[240,955,957],{"class":242,"line":956},65,[240,958,959],{"class":469},"        // Echo the message back to the sender\n",[240,961,963,965,967],{"class":242,"line":962},66,[240,964,732],{"class":250},[240,966,735],{"class":313},[240,968,969],{"class":250},"(message);\n",[240,971,973],{"class":242,"line":972},67,[240,974,810],{"class":250},[240,976,978],{"class":242,"line":977},68,[240,979,268],{"emptyLinePlaceholder":267},[240,981,983,986,988,990],{"class":242,"line":982},69,[240,984,985],{"class":313},"      close",[240,987,334],{"class":250},[240,989,695],{"class":694},[240,991,698],{"class":250},[240,993,995,997,999,1001,1004],{"class":242,"line":994},70,[240,996,704],{"class":250},[240,998,707],{"class":313},[240,1000,334],{"class":250},[240,1002,1003],{"class":257},"\"[close]\"",[240,1005,715],{"class":250},[240,1007,1009,1011,1013,1015,1017,1019,1021,1023,1026],{"class":242,"line":1008},71,[240,1010,732],{"class":250},[240,1012,788],{"class":313},[240,1014,334],{"class":250},[240,1016,767],{"class":257},[240,1018,340],{"class":250},[240,1020,797],{"class":257},[240,1022,695],{"class":250},[240,1024,1025],{"class":257},"} has left the chat!`",[240,1027,743],{"class":250},[240,1029,1031,1033,1036,1038,1040],{"class":242,"line":1030},72,[240,1032,732],{"class":250},[240,1034,1035],{"class":313},"unsubscribe",[240,1037,334],{"class":250},[240,1039,767],{"class":257},[240,1041,743],{"class":250},[240,1043,1045],{"class":242,"line":1044},73,[240,1046,810],{"class":250},[240,1048,1050],{"class":242,"line":1049},74,[240,1051,1052],{"class":250},"    },\n",[240,1054,1056],{"class":242,"line":1055},75,[240,1057,1058],{"class":469},"    // Non-upgrade requests get the playground page.\n",[240,1060,1062,1065,1068],{"class":242,"line":1061},76,[240,1063,1064],{"class":250},"    () ",[240,1066,1067],{"class":246},"=>",[240,1069,1070],{"class":250}," playground,\n",[240,1072,1074],{"class":242,"line":1073},77,[240,1075,1076],{"class":250},"  ),\n",[240,1078,1080],{"class":242,"line":1079},78,[240,1081,743],{"class":250},[240,1083,1085],{"class":242,"line":1084},79,[240,1086,268],{"emptyLinePlaceholder":267},[240,1088,1090,1092],{"class":242,"line":1089},80,[240,1091,228],{"class":313},[240,1093,359],{"class":250},[240,1095,1097,1099,1101],{"class":242,"line":1096},81,[240,1098,365],{"class":250},[240,1100,368],{"class":313},[240,1102,371],{"class":250},[240,1104,1106],{"class":242,"line":1105},82,[240,1107,377],{"class":250},[1109,1110,1112],"h3",{"id":1111},"handling-http-requests","Handling HTTP requests",[199,1114,1115,1116,1119],{},"By default, a WebSocket route responds with ",[219,1117,1118],{},"426 Upgrade Required"," to any request that is not a WebSocket upgrade.",[199,1121,1122,1123,1125],{},"You can pass an optional HTTP handler as the second argument to ",[219,1124,221],{}," to serve regular (non-upgrade) requests on the same route. WebSocket upgrade requests still go to the hooks.",[231,1127,1129],{"className":233,"code":1128,"language":235,"meta":236,"style":236},"app.get(\n  \"/_ws\",\n  defineWebSocketHandler(\n    { message: (peer, message) => peer.send(message.text()) },\n    () => \"Send a WebSocket upgrade request to connect.\",\n  ),\n);\n",[219,1130,1131,1139,1146,1152,1186,1197,1201],{"__ignoreMap":236},[240,1132,1133,1135,1137],{"class":242,"line":243},[240,1134,328],{"class":250},[240,1136,331],{"class":313},[240,1138,660],{"class":250},[240,1140,1141,1144],{"class":242,"line":264},[240,1142,1143],{"class":257},"  \"/_ws\"",[240,1145,669],{"class":250},[240,1147,1148,1150],{"class":242,"line":271},[240,1149,675],{"class":313},[240,1151,660],{"class":250},[240,1153,1154,1157,1159,1162,1164,1166,1168,1171,1173,1176,1178,1181,1183],{"class":242,"line":292},[240,1155,1156],{"class":250},"    { ",[240,1158,830],{"class":313},[240,1160,1161],{"class":250},": (",[240,1163,695],{"class":694},[240,1165,340],{"class":250},[240,1167,830],{"class":694},[240,1169,1170],{"class":250},") ",[240,1172,1067],{"class":246},[240,1174,1175],{"class":250}," peer.",[240,1177,735],{"class":313},[240,1179,1180],{"class":250},"(message.",[240,1182,863],{"class":313},[240,1184,1185],{"class":250},"()) },\n",[240,1187,1188,1190,1192,1195],{"class":242,"line":297},[240,1189,1064],{"class":250},[240,1191,1067],{"class":246},[240,1193,1194],{"class":257}," \"Send a WebSocket upgrade request to connect.\"",[240,1196,669],{"class":250},[240,1198,1199],{"class":242,"line":320},[240,1200,1076],{"class":250},[240,1202,1203],{"class":242,"line":325},[240,1204,743],{"class":250},[211,1206,1208],{"id":1207},"server-sent-events-sse","Server-Sent Events (SSE)",[199,1210,1211,1212,209],{},"As an alternative to WebSockets, you can use ",[203,1213,1216],{"href":1214,"rel":1215},"https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events",[207],"Server-sent events",[199,1218,1219,1220,1223],{},"H3 has a built-in API to create server-sent events using ",[219,1221,1222],{},"createEventStream(event)"," utility.",[1109,1225,1227],{"id":1226},"example","Example",[231,1229,1232],{"className":233,"code":1230,"filename":1231,"language":235,"meta":236,"style":236},"import { H3, serve, createEventStream } from \"h3\";\n\nexport const app = new H3();\n\napp.get(\"/\", (event) => {\n  const eventStream = createEventStream(event);\n\n  // Send a message every second\n  const interval = setInterval(async () => {\n    await eventStream.push(\"Hello world\");\n  }, 1000);\n\n  // cleanup the interval when the connection is terminated or the writer is closed\n  eventStream.onClosed(() => {\n    console.log(\"Connection closed\");\n    clearInterval(interval);\n  });\n\n  return eventStream.send();\n});\n\nserve(app);\n","server-sent-events.mjs",[219,1233,1234,1247,1251,1267,1271,1295,1311,1315,1320,1344,1362,1372,1376,1381,1396,1410,1418,1423,1427,1438,1442,1446],{"__ignoreMap":236},[240,1235,1236,1238,1241,1243,1245],{"class":242,"line":243},[240,1237,247],{"class":246},[240,1239,1240],{"class":250}," { H3, serve, createEventStream } ",[240,1242,254],{"class":246},[240,1244,258],{"class":257},[240,1246,261],{"class":250},[240,1248,1249],{"class":242,"line":264},[240,1250,268],{"emptyLinePlaceholder":267},[240,1252,1253,1255,1257,1259,1261,1263,1265],{"class":242,"line":271},[240,1254,447],{"class":246},[240,1256,450],{"class":246},[240,1258,304],{"class":303},[240,1260,307],{"class":246},[240,1262,310],{"class":246},[240,1264,314],{"class":313},[240,1266,317],{"class":250},[240,1268,1269],{"class":242,"line":292},[240,1270,268],{"emptyLinePlaceholder":267},[240,1272,1273,1275,1277,1279,1282,1285,1288,1290,1292],{"class":242,"line":297},[240,1274,328],{"class":250},[240,1276,331],{"class":313},[240,1278,334],{"class":250},[240,1280,1281],{"class":257},"\"/\"",[240,1283,1284],{"class":250},", (",[240,1286,1287],{"class":694},"event",[240,1289,1170],{"class":250},[240,1291,1067],{"class":246},[240,1293,1294],{"class":250}," {\n",[240,1296,1297,1300,1303,1305,1308],{"class":242,"line":320},[240,1298,1299],{"class":246},"  const",[240,1301,1302],{"class":303}," eventStream",[240,1304,307],{"class":246},[240,1306,1307],{"class":313}," createEventStream",[240,1309,1310],{"class":250},"(event);\n",[240,1312,1313],{"class":242,"line":325},[240,1314,268],{"emptyLinePlaceholder":267},[240,1316,1317],{"class":242,"line":349},[240,1318,1319],{"class":469},"  // Send a message every second\n",[240,1321,1322,1324,1327,1329,1332,1334,1337,1340,1342],{"class":242,"line":354},[240,1323,1299],{"class":246},[240,1325,1326],{"class":303}," interval",[240,1328,307],{"class":246},[240,1330,1331],{"class":313}," setInterval",[240,1333,334],{"class":250},[240,1335,1336],{"class":246},"async",[240,1338,1339],{"class":250}," () ",[240,1341,1067],{"class":246},[240,1343,1294],{"class":250},[240,1345,1346,1349,1352,1355,1357,1360],{"class":242,"line":362},[240,1347,1348],{"class":246},"    await",[240,1350,1351],{"class":250}," eventStream.",[240,1353,1354],{"class":313},"push",[240,1356,334],{"class":250},[240,1358,1359],{"class":257},"\"Hello world\"",[240,1361,743],{"class":250},[240,1363,1364,1367,1370],{"class":242,"line":374},[240,1365,1366],{"class":250},"  }, ",[240,1368,1369],{"class":303},"1000",[240,1371,743],{"class":250},[240,1373,1374],{"class":242,"line":508},[240,1375,268],{"emptyLinePlaceholder":267},[240,1377,1378],{"class":242,"line":514},[240,1379,1380],{"class":469},"  // cleanup the interval when the connection is terminated or the writer is closed\n",[240,1382,1383,1386,1389,1392,1394],{"class":242,"line":520},[240,1384,1385],{"class":250},"  eventStream.",[240,1387,1388],{"class":313},"onClosed",[240,1390,1391],{"class":250},"(() ",[240,1393,1067],{"class":246},[240,1395,1294],{"class":250},[240,1397,1398,1401,1403,1405,1408],{"class":242,"line":526},[240,1399,1400],{"class":250},"    console.",[240,1402,707],{"class":313},[240,1404,334],{"class":250},[240,1406,1407],{"class":257},"\"Connection closed\"",[240,1409,743],{"class":250},[240,1411,1412,1415],{"class":242,"line":532},[240,1413,1414],{"class":313},"    clearInterval",[240,1416,1417],{"class":250},"(interval);\n",[240,1419,1420],{"class":242,"line":538},[240,1421,1422],{"class":250},"  });\n",[240,1424,1425],{"class":242,"line":544},[240,1426,268],{"emptyLinePlaceholder":267},[240,1428,1429,1432,1434,1436],{"class":242,"line":550},[240,1430,1431],{"class":246},"  return",[240,1433,1351],{"class":250},[240,1435,735],{"class":313},[240,1437,317],{"class":250},[240,1439,1440],{"class":242,"line":556},[240,1441,377],{"class":250},[240,1443,1444],{"class":242,"line":562},[240,1445,268],{"emptyLinePlaceholder":267},[240,1447,1448,1450],{"class":242,"line":568},[240,1449,228],{"class":313},[240,1451,1452],{"class":250},"(app);\n",[1454,1455,1456],"style",{},"html pre.shiki code .so5gQ, html code.shiki .so5gQ{--shiki-light:#D73A49;--shiki-default:#F97583;--shiki-dark:#F97583}html pre.shiki code .slsVL, html code.shiki .slsVL{--shiki-light:#24292E;--shiki-default:#E1E4E8;--shiki-dark:#E1E4E8}html pre.shiki code .sfrk1, html code.shiki .sfrk1{--shiki-light:#032F62;--shiki-default:#9ECBFF;--shiki-dark:#9ECBFF}html pre.shiki code .suiK_, html code.shiki .suiK_{--shiki-light:#005CC5;--shiki-default:#79B8FF;--shiki-dark:#79B8FF}html pre.shiki code .shcOC, html code.shiki .shcOC{--shiki-light:#6F42C1;--shiki-default:#B392F0;--shiki-dark:#B392F0}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sCsY4, html code.shiki .sCsY4{--shiki-light:#6A737D;--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sQHwn, html code.shiki .sQHwn{--shiki-light:#E36209;--shiki-default:#FFAB70;--shiki-dark:#FFAB70}",{"title":236,"searchDepth":264,"depth":264,"links":1458},[1459,1462],{"id":213,"depth":264,"text":214,"children":1460},[1461],{"id":1111,"depth":271,"text":1112},{"id":1207,"depth":264,"text":1208,"children":1463},[1464],{"id":1226,"depth":271,"text":1227},"H3 has built-in utilities for cross platform WebSocket and Server-Sent Events.","md",{"automd":267,"icon":84},{"icon":84},{"title":81,"description":1465},"6B0hE10wq-9J2cznnebfP7tm_UPZu256i8pdmBM8Muc",[1472,1474],{"title":76,"path":77,"stem":78,"description":1473,"icon":79,"children":-1},"H3 plugins allow you to extend an H3 app instance with reusable logic.",{"title":86,"path":87,"stem":88,"description":236,"icon":89,"children":-1},1783690731321]