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