[Node.js] HTTP2
https://btholt.github.io/complete-intro-to-realtime/intro-to-http2-push
- long-running HTTP call
- HTTP2 PUSH
FE:
async function getNewMsgs() {
let reader;
const utf8Decoder = new TextDecoder("utf-8");
try {
const res = await fetch("/msgs");
reader = res.body.getReader();
} catch (e) {
console.log("connection error", e);
}
let done;
presence.innerText = "🟢";
do {
let readerResponse;
try {
readerResponse = await reader.read();
} catch (e) {
console.error("reader failed", e);
presence.innerText = "🔴";
return;
}
done = readerResponse.done;
const chunk = utf8Decoder.decode(readerResponse.value, { stream: true });
if (chunk) {
try {
const json = JSON.parse(chunk);
allChat = json.msg;
render();
} catch (e) {
console.error("parse error", e);
}
}
console.log("done", done);
} while (!done);
// in theory, if our http2 connection closed, `done` would come back
// as true and we'd no longer be connected
presence.innerText = "🔴";
}
A few things here:
- We're still using fetch, but instead of just saying res.json(), we're opening a readable stream with getReader() and now we can expect multiple responses. Up front we're just logging out the first chunk we get back, but we can now expect that to respond multiple times.
- We're using the green and red circle to show the user if they're still connected to the socket. If it's red, we know we've disconnected. If that happens, you just need to refresh the page. In a production app, you'd just need to reconnect a new socket and keep listening. But you can do that on your own time.
- We need to decode the response that comes over the socket. That's what the utf8Decoder does.
- I'm not making you do the POST again. It's the same logic as last time.
- If you look at the network request in your network console, notice that there isn't a status code or anything. According to the browser, this request is still actually in flight.
BE:
import http2 from "http2";
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import handler from "serve-handler";
import nanobuffer from "nanobuffer";
let connections = [];
const msg = new nanobuffer(50);
const getMsgs = () => Array.from(msg).reverse();
msg.push({
user: "brian?",
text: "hi",
time: Date.now(),
});
// openssl req -new -newkey rsa:2048 -new -nodes -keyout key.pem -out csr.pem
// openssl x509 -req -days 365 -in csr.pem -signkey key.pem -out server.crt
// http2 only works over HTTPS
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const server = http2.createSecureServer({
cert: fs.readFileSync(path.join(__dirname, "/../server.crt")),
key: fs.readFileSync(path.join(__dirname, "/../key.pem")),
});
server.on("stream", (stream, headers) => {
const method = headers[":method"];
const path = headers[":path"];
// streams will open for everything, we want just GETs on /msgs
if (path === "/msgs" && method === "GET") {
// immediately respond with 200 OK and encoding
stream.respond({
":status": 200,
"content-type": "text/plain; charset=utf-8",
});
// write the first response
stream.write(JSON.stringify({ msg: getMsgs() }));
// keep track of the connection
connections.push(stream);
// when the connection closes, stop keeping track of it
stream.on("close", () => {
connections = connections.filter((s) => s !== stream);
});
}
});
server.on("request", async (req, res) => {
const path = req.headers[":path"];
const method = req.headers[":method"];
if (path !== "/msgs") {
// handle the static assets
return handler(req, res, {
public: "./frontend",
});
} else if (method === "POST") {
// get data out of post
const buffers = [];
for await (const chunk of req) {
buffers.push(chunk);
}
const data = Buffer.concat(buffers).toString();
const { user, text } = JSON.parse(data);
msg.push({
user,
text,
time: Date.now(),
});
// all done with the request
res.end();
// notify all connected users
connections.forEach((stream) => {
stream.write(JSON.stringify({ msg: getMsgs() }));
});
}
});
// start listening
const port = process.env.PORT || 8080;
server.listen(port, () =>
console.log(
`Server running at https://localhost:${port} - make sure you're on httpS, not http`
)
);
分类:
Node.js
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2020-07-15 [XState] Code a state machine
2018-07-15 [CSS] Useful CSS tool for Web designer and developer