Skip to content

Instantly share code, notes, and snippets.

@guest271314
Created July 13, 2025 17:51
Show Gist options
  • Save guest271314/e699b9abf4b91e09d74a488a5f48bb48 to your computer and use it in GitHub Desktop.
Save guest271314/e699b9abf4b91e09d74a488a5f48bb48 to your computer and use it in GitHub Desktop.
Deno WebTrasport server
import certificates from "./cert.json" with { type: "json" };
const serverCertificateHashes = [{
algorithm: "sha-256",
value: Uint8Array.from(certificates[0].hash.digest)
}];
let requests = 0;
async function handleTransport(wt) {
let incomingTotalLength = 0;
let incomingCurrentLength = 0;
const buffer = new ArrayBuffer(0, { maxByteLength: 4 });
const view = new DataView(buffer);
const encoder = new TextEncoder;
const decoder = new TextDecoder;
await wt.ready;
try {
for await (const { readable, writable } of wt.incomingBidirectionalStreams) {
const writer = writable.getWriter();
await readable.pipeTo(new WritableStream({
async write(value) {
if (incomingTotalLength === 0 && incomingCurrentLength === 0) {
buffer.resize(4);
for (let i = 0;i < 4; i++) {
view.setUint8(i, value[i]);
}
incomingTotalLength = view.getUint32(0, true);
console.log(value.length, incomingTotalLength);
value = value.subarray(4);
}
const encoded = encoder.encode(decoder.decode(value).toUpperCase());
await writer.ready;
await writer.write(encoded);
await writer.ready;
incomingCurrentLength += encoded.length;
console.log(`Done writing ${encoded.length} bytes to writable, ${incomingCurrentLength} of ${incomingTotalLength} bytes written.`);
},
close() {
console.log("readable closed");
}
})).then(() => console.log("writable closed")).catch((e) => console.log(e));
buffer.resize(0);
incomingTotalLength = incomingCurrentLength = 0;
console.log(`Done streaming request ${requests++}`);
continue;
}
} catch (e) {
console.log("handleTransport caught", e);
}
return `Done streaming`;
}
const server = new Deno.QuicEndpoint({
hostname: "0.0.0.0",
port: 8080
});
const listener = server.listen({
cert: certificates[0].pem,
key: certificates[0].privateKey,
alpnProtocols: ["h3"]
});
console.log({ server, listener });
try {
for await (const conn of listener) {
const wt = await Deno.upgradeWebTransport(conn).catch((e) => console.log("upgrade caught", e));
try {
await handleTransport(wt).then(console.log).catch(console.error);
} catch (e) {
console.log(e);
} finally {
continue;
}
}
} catch (e) {
console.log("caught", e);
} finally {
try {
listener.stop();
server.close();
} catch (e) {
console.log("caught again", e);
}
}
@guest271314
Copy link
Author

Client

const serverCertificateHashes = [{
  algorithm: "sha-256",
  value: Uint8Array.of(1,2,3...)
}];
if (!/Deno|Chrome|Firefox/i.test(navigator.userAgent)) {
  let {
    WebTransport,
    quicheLoaded
  } = await import("./node_modules/@fails-components/webtransport/lib/index.node.js");
  await quicheLoaded;
  globalThis.WebTransport = WebTransport;
}
async function createStream(wt, data) {
  const abortable = new AbortController;
  const {
    signal
  } = abortable;
  const {
    readable,
    writable
  } = await wt.createBidirectionalStream();
  let header = new Uint8Array(Uint32Array.from({
    length: 4
  }, (_, index) => data.length >> index * 8 & 255));
  let view = new DataView(header.buffer);
  let outgoingTotalLength = view.getUint32(0, true);
  console.log({
    outgoingTotalLength
  });
  let incomingTotalLength = 0;
  const writer = writable.getWriter();
  await writer.ready;
  await writer.write(header).then(() => console.log(`Outgoing total length ${outgoingTotalLength} written.`));
  await writer.ready;
  await writer.write(data).then(() => console.log(`${data.length} bytes written.`)).catch((e) => console.log(e));
  await writer.ready;
  for await (const value of readable.pipeThrough(new TextDecoderStream)) {
    console.log(incomingTotalLength += value.length);
    if (incomingTotalLength === outgoingTotalLength) {
      await writer.ready;
      await writer.close().catch((e) => {});
      await writer.closed;
      writer.releaseLock();
      break;
    }
  }
  await readable.cancel().catch((e) => console.log(e));
  console.log(readable.locked);
  return "Stream done";
}
const client = new WebTransport(`https://127.0.0.1:8080`, {
  serverCertificateHashes
});
client.closed.then(() => console.log("client closed")).catch(console.log);
await client.ready;
const encoder = new TextEncoder;
var data = encoder.encode("x".repeat(1024 ** 2));
var res = await createStream(client, data);
console.log(res);
if (globalThis?.process?.exit()) {
  process.exit();
} else {
  // globalThis.close();
}

// write multiple streams to same connection
// var data = encoder.encode("x".repeat(1024 ** 2));
// var res = await createStream(client, data);
// var data = encoder.encode("x".repeat(1024 ** 2));
// var res = await createStream(client, data);

// client.close();

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment