From 82f79e801744d399b15b04b1d325e8c7ffa6ada1 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Tue, 28 May 2024 21:31:45 +0530 Subject: [PATCH 1/4] wip --- ext/node/polyfills/http2.ts | 14 +- tests/unit_node/http2_test.ts | 303 +++++++++++++++++++--------------- 2 files changed, 173 insertions(+), 144 deletions(-) diff --git a/ext/node/polyfills/http2.ts b/ext/node/polyfills/http2.ts index 59756dd0f26cef..e15dbb6283e9dc 100644 --- a/ext/node/polyfills/http2.ts +++ b/ext/node/polyfills/http2.ts @@ -933,25 +933,23 @@ export class ClientHttp2Stream extends Duplex { // TODO(bartlomieju): clean up _write(chunk, encoding, callback?: () => void) { - debugHttp2(">>> _write", callback); + debugHttp2(">>> _write", encoding, callback); if (typeof encoding === "function") { callback = encoding; - encoding = "utf8"; + encoding = this.#encoding; } let data; - if (typeof encoding === "string") { + if (encoding === "utf8") { data = ENCODER.encode(chunk); - } else { + } else if (encoding === "buffer") { + this.#encoding = encoding; data = chunk.buffer; } this.#requestPromise .then(() => { debugHttp2(">>> _write", this.#rid, data, encoding, callback); - return op_http2_client_send_data( - this.#rid, - data, - ); + return op_http2_client_send_data(this.#rid, new Uint8Array(data)); }) .then(() => { callback?.(); diff --git a/tests/unit_node/http2_test.ts b/tests/unit_node/http2_test.ts index 872e6641e29ca4..06799214afb493 100644 --- a/tests/unit_node/http2_test.ts +++ b/tests/unit_node/http2_test.ts @@ -5,90 +5,178 @@ import * as net from "node:net"; import { assert, assertEquals } from "@std/assert/mod.ts"; import { curlRequest } from "../unit/test_util.ts"; -for (const url of ["http://127.0.0.1:4246", "https://127.0.0.1:4247"]) { - Deno.test(`[node/http2 client] ${url}`, { - ignore: Deno.build.os === "windows", - }, async () => { - // Create a server to respond to the HTTP2 requests - const client = http2.connect(url, {}); - client.on("error", (err) => console.error(err)); - - const req = client.request({ ":method": "POST", ":path": "/" }, { - waitForTrailers: true, - }); - - let receivedTrailers; - let receivedHeaders; - let receivedData = ""; - - req.on("response", (headers, _flags) => { - receivedHeaders = headers; - }); - - req.write("hello"); - req.setEncoding("utf8"); - - req.on("wantTrailers", () => { - req.sendTrailers({ foo: "bar" }); - }); - - req.on("trailers", (trailers, _flags) => { - receivedTrailers = trailers; - }); - - req.on("data", (chunk) => { - receivedData += chunk; - }); - req.end(); - - const { promise, resolve } = Promise.withResolvers(); - setTimeout(() => { - try { - client.close(); - } catch (_) { - // pass - } - resolve(); - }, 2000); - - await promise; - assertEquals(receivedHeaders, { ":status": 200 }); - assertEquals(receivedData, "hello world\n"); - - assertEquals(receivedTrailers, { - "abc": "def", - "opr": "stv", - "foo": "bar", - }); - }); -} - -Deno.test(`[node/http2 client createConnection]`, { - ignore: Deno.build.os === "windows", -}, async () => { - const url = "http://127.0.0.1:4246"; - const createConnDeferred = Promise.withResolvers(); +// for (const url of ["http://127.0.0.1:4246", "https://127.0.0.1:4247"]) { +// Deno.test(`[node/http2 client] ${url}`, { +// ignore: Deno.build.os === "windows", +// }, async () => { +// // Create a server to respond to the HTTP2 requests +// const client = http2.connect(url, {}); +// client.on("error", (err) => console.error(err)); + +// const req = client.request({ ":method": "POST", ":path": "/" }, { +// waitForTrailers: true, +// }); + +// let receivedTrailers; +// let receivedHeaders; +// let receivedData = ""; + +// req.on("response", (headers, _flags) => { +// receivedHeaders = headers; +// }); + +// req.write("hello"); +// req.setEncoding("utf8"); + +// req.on("wantTrailers", () => { +// req.sendTrailers({ foo: "bar" }); +// }); + +// req.on("trailers", (trailers, _flags) => { +// receivedTrailers = trailers; +// }); + +// req.on("data", (chunk) => { +// receivedData += chunk; +// }); +// req.end(); + +// const { promise, resolve } = Promise.withResolvers(); +// setTimeout(() => { +// try { +// client.close(); +// } catch (_) { +// // pass +// } +// resolve(); +// }, 2000); + +// await promise; +// assertEquals(receivedHeaders, { ":status": 200 }); +// assertEquals(receivedData, "hello world\n"); + +// assertEquals(receivedTrailers, { +// "abc": "def", +// "opr": "stv", +// "foo": "bar", +// }); +// }); +// } + +// Deno.test(`[node/http2 client createConnection]`, { +// ignore: Deno.build.os === "windows", +// }, async () => { +// const url = "http://127.0.0.1:4246"; +// const createConnDeferred = Promise.withResolvers(); +// // Create a server to respond to the HTTP2 requests +// const client = http2.connect(url, { +// createConnection() { +// const socket = net.connect({ host: "127.0.0.1", port: 4246 }); + +// socket.on("connect", () => { +// createConnDeferred.resolve(); +// }); + +// return socket; +// }, +// }); +// client.on("error", (err) => console.error(err)); + +// const req = client.request({ ":method": "POST", ":path": "/" }); + +// let receivedData = ""; + +// req.write("hello"); +// req.setEncoding("utf8"); + +// req.on("data", (chunk) => { +// receivedData += chunk; +// }); +// req.end(); + +// const endPromise = Promise.withResolvers(); +// setTimeout(() => { +// try { +// client.close(); +// } catch (_) { +// // pass +// } +// endPromise.resolve(); +// }, 2000); + +// await createConnDeferred.promise; +// await endPromise.promise; +// assertEquals(receivedData, "hello world\n"); +// }); + +// Deno.test("[node/http2 client GET https://www.example.com]", async () => { +// const clientSession = http2.connect("https://www.example.com"); +// const req = clientSession.request({ +// ":method": "GET", +// ":path": "/", +// }); +// let headers = {}; +// let status: number | undefined = 0; +// let chunk = new Uint8Array(); +// const endPromise = Promise.withResolvers(); +// req.on("response", (h) => { +// status = h[":status"]; +// headers = h; +// }); +// req.on("data", (c) => { +// chunk = c; +// }); +// req.on("end", () => { +// clientSession.close(); +// req.close(); +// endPromise.resolve(); +// }); +// req.end(); +// await endPromise.promise; +// assert(Object.keys(headers).length > 0); +// assertEquals(status, 200); +// assert(chunk.length > 0); +// }); + +// Deno.test("[node/http2.createServer()]", { +// // TODO(satyarohith): enable the test on windows. +// ignore: Deno.build.os === "windows", +// }, async () => { +// const server = http2.createServer((_req, res) => { +// res.setHeader("Content-Type", "text/html"); +// res.setHeader("X-Foo", "bar"); +// res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" }); +// res.write("Hello, World!"); +// res.end(); +// }); +// server.listen(0); +// const port = ( server.address()).port; +// const endpoint = `http://localhost:${port}`; + +// const response = await curlRequest([ +// endpoint, +// "--http2-prior-knowledge", +// ]); +// assertEquals(response, "Hello, World!"); +// server.close(); +// // Wait to avoid leaking the timer from here +// // https://github.com/denoland/deno/blob/749b6e45e58ac87188027f79fe403d130f86bd73/ext/node/polyfills/net.ts#L2396-L2402 +// // Issue: https://github.com/denoland/deno/issues/22764 +// await new Promise((resolve) => server.on("close", resolve)); +// }); + + +Deno.test("[node/http2 client] write buffer on request stream works", async () => { + const url = "https://localhost:5545"; // Create a server to respond to the HTTP2 requests - const client = http2.connect(url, { - createConnection() { - const socket = net.connect({ host: "127.0.0.1", port: 4246 }); - - socket.on("connect", () => { - createConnDeferred.resolve(); - }); - - return socket; - }, - }); + const client = http2.connect(url) client.on("error", (err) => console.error(err)); - const req = client.request({ ":method": "POST", ":path": "/" }); + const req = client.request({ ":method": "POST", ":path": "/echo_server" }); + req.write(new Uint8Array(new TextEncoder().encode("amazing")), "binary"); let receivedData = ""; - - req.write("hello"); req.setEncoding("utf8"); - req.on("data", (chunk) => { receivedData += chunk; }); @@ -104,63 +192,6 @@ Deno.test(`[node/http2 client createConnection]`, { endPromise.resolve(); }, 2000); - await createConnDeferred.promise; - await endPromise.promise; - assertEquals(receivedData, "hello world\n"); -}); - -Deno.test("[node/http2 client GET https://www.example.com]", async () => { - const clientSession = http2.connect("https://www.example.com"); - const req = clientSession.request({ - ":method": "GET", - ":path": "/", - }); - let headers = {}; - let status: number | undefined = 0; - let chunk = new Uint8Array(); - const endPromise = Promise.withResolvers(); - req.on("response", (h) => { - status = h[":status"]; - headers = h; - }); - req.on("data", (c) => { - chunk = c; - }); - req.on("end", () => { - clientSession.close(); - req.close(); - endPromise.resolve(); - }); - req.end(); await endPromise.promise; - assert(Object.keys(headers).length > 0); - assertEquals(status, 200); - assert(chunk.length > 0); -}); - -Deno.test("[node/http2.createServer()]", { - // TODO(satyarohith): enable the test on windows. - ignore: Deno.build.os === "windows", -}, async () => { - const server = http2.createServer((_req, res) => { - res.setHeader("Content-Type", "text/html"); - res.setHeader("X-Foo", "bar"); - res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" }); - res.write("Hello, World!"); - res.end(); - }); - server.listen(0); - const port = ( server.address()).port; - const endpoint = `http://localhost:${port}`; - - const response = await curlRequest([ - endpoint, - "--http2-prior-knowledge", - ]); - assertEquals(response, "Hello, World!"); - server.close(); - // Wait to avoid leaking the timer from here - // https://github.com/denoland/deno/blob/749b6e45e58ac87188027f79fe403d130f86bd73/ext/node/polyfills/net.ts#L2396-L2402 - // Issue: https://github.com/denoland/deno/issues/22764 - await new Promise((resolve) => server.on("close", resolve)); + assertEquals(receivedData, "amazing"); }); From 02e09827354e02abfbb90a9600814649849f6755 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Tue, 28 May 2024 21:47:25 +0530 Subject: [PATCH 2/4] wip2 --- ext/node/polyfills/http2.ts | 4 ++-- tests/unit_node/http2_test.ts | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/ext/node/polyfills/http2.ts b/ext/node/polyfills/http2.ts index e15dbb6283e9dc..a4d33c496f59cf 100644 --- a/ext/node/polyfills/http2.ts +++ b/ext/node/polyfills/http2.ts @@ -120,7 +120,7 @@ const SESSION_FLAGS_DESTROYED = 0x4; const ENCODER = new TextEncoder(); type Http2Headers = Record; -const debugHttp2Enabled = false; +const debugHttp2Enabled = true; function debugHttp2(...args) { if (debugHttp2Enabled) { console.log(...args); @@ -933,7 +933,7 @@ export class ClientHttp2Stream extends Duplex { // TODO(bartlomieju): clean up _write(chunk, encoding, callback?: () => void) { - debugHttp2(">>> _write", encoding, callback); + debugHttp2(">>> _write", {encoding}, callback); if (typeof encoding === "function") { callback = encoding; encoding = this.#encoding; diff --git a/tests/unit_node/http2_test.ts b/tests/unit_node/http2_test.ts index 06799214afb493..96925d813ab5ad 100644 --- a/tests/unit_node/http2_test.ts +++ b/tests/unit_node/http2_test.ts @@ -1,6 +1,7 @@ // Copyright 2018-2024 the Deno authors. All rights reserved. MIT license. import * as http2 from "node:http2"; +import { Buffer } from "node:buffer"; import * as net from "node:net"; import { assert, assertEquals } from "@std/assert/mod.ts"; import { curlRequest } from "../unit/test_util.ts"; @@ -173,7 +174,7 @@ Deno.test("[node/http2 client] write buffer on request stream works", async () = client.on("error", (err) => console.error(err)); const req = client.request({ ":method": "POST", ":path": "/echo_server" }); - req.write(new Uint8Array(new TextEncoder().encode("amazing")), "binary"); + req.write(Buffer.from("amazing")); let receivedData = ""; req.setEncoding("utf8"); From 3d7466ff73110bddf1867457c94d6d9c3e880068 Mon Sep 17 00:00:00 2001 From: Satya Rohith Date: Wed, 29 May 2024 10:07:32 +0530 Subject: [PATCH 3/4] wip --- tests/unit_node/http2_test.ts | 25 ++++++++++++++++++++----- tests/unit_node/testdata/green.jpg | Bin 0 -> 361 bytes 2 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 tests/unit_node/testdata/green.jpg diff --git a/tests/unit_node/http2_test.ts b/tests/unit_node/http2_test.ts index 96925d813ab5ad..53137e53a97e46 100644 --- a/tests/unit_node/http2_test.ts +++ b/tests/unit_node/http2_test.ts @@ -2,6 +2,10 @@ import * as http2 from "node:http2"; import { Buffer } from "node:buffer"; +import fs from "node:fs"; +import { readFile } from "node:fs/promises"; +import { fileURLToPath } from "node:url"; +import { join } from "node:path"; import * as net from "node:net"; import { assert, assertEquals } from "@std/assert/mod.ts"; import { curlRequest } from "../unit/test_util.ts"; @@ -173,13 +177,21 @@ Deno.test("[node/http2 client] write buffer on request stream works", async () = const client = http2.connect(url) client.on("error", (err) => console.error(err)); + const imagePath = join(import.meta.dirname!, "testdata", "green.jpg"); + console.log({ imagePath }) + const buffer = await readFile(imagePath); + console.log({ bufferLength: buffer.length }) + // const imageLength = buffer.length; + // console.log({ imageLength }); const req = client.request({ ":method": "POST", ":path": "/echo_server" }); - req.write(Buffer.from("amazing")); + // req.write(new Uint8Array([1, 2, 3, 4]), (err) => console.error("write cb", err)); + req.write(buffer, (err) => console.error("write cb", err)); - let receivedData = ""; - req.setEncoding("utf8"); + let chunks: Buffer; req.on("data", (chunk) => { - receivedData += chunk; + console.log("chunk receivedData", chunk); + // receivedData = Buffer.concat([receivedData, chunk]); + chunks = chunk; }); req.end(); @@ -194,5 +206,8 @@ Deno.test("[node/http2 client] write buffer on request stream works", async () = }, 2000); await endPromise.promise; - assertEquals(receivedData, "amazing"); + console.log("compare", buffer.compare(chunks!) === 0, buffer.length, chunks!.length) + // console.log("receivedData", receivedData); + // const expectedBuffer = fs.readFileSync("/Users/sr/c/denoland/deno/cat_dog.webp"); + assertEquals(chunks!, buffer); }); diff --git a/tests/unit_node/testdata/green.jpg b/tests/unit_node/testdata/green.jpg new file mode 100644 index 0000000000000000000000000000000000000000..72b51899e4883cde2ebc9b3409cd2ac1d78d9d88 GIT binary patch literal 361 zcmex= Date: Wed, 29 May 2024 10:16:19 +0530 Subject: [PATCH 4/4] add test for image uploads --- ext/node/polyfills/http2.ts | 4 +- tests/unit_node/http2_test.ts | 352 +++++++++++++++++----------------- 2 files changed, 174 insertions(+), 182 deletions(-) diff --git a/ext/node/polyfills/http2.ts b/ext/node/polyfills/http2.ts index a4d33c496f59cf..e15dbb6283e9dc 100644 --- a/ext/node/polyfills/http2.ts +++ b/ext/node/polyfills/http2.ts @@ -120,7 +120,7 @@ const SESSION_FLAGS_DESTROYED = 0x4; const ENCODER = new TextEncoder(); type Http2Headers = Record; -const debugHttp2Enabled = true; +const debugHttp2Enabled = false; function debugHttp2(...args) { if (debugHttp2Enabled) { console.log(...args); @@ -933,7 +933,7 @@ export class ClientHttp2Stream extends Duplex { // TODO(bartlomieju): clean up _write(chunk, encoding, callback?: () => void) { - debugHttp2(">>> _write", {encoding}, callback); + debugHttp2(">>> _write", encoding, callback); if (typeof encoding === "function") { callback = encoding; encoding = this.#encoding; diff --git a/tests/unit_node/http2_test.ts b/tests/unit_node/http2_test.ts index 53137e53a97e46..f2604b344c5742 100644 --- a/tests/unit_node/http2_test.ts +++ b/tests/unit_node/http2_test.ts @@ -2,196 +2,191 @@ import * as http2 from "node:http2"; import { Buffer } from "node:buffer"; -import fs from "node:fs"; import { readFile } from "node:fs/promises"; -import { fileURLToPath } from "node:url"; import { join } from "node:path"; import * as net from "node:net"; import { assert, assertEquals } from "@std/assert/mod.ts"; import { curlRequest } from "../unit/test_util.ts"; -// for (const url of ["http://127.0.0.1:4246", "https://127.0.0.1:4247"]) { -// Deno.test(`[node/http2 client] ${url}`, { -// ignore: Deno.build.os === "windows", -// }, async () => { -// // Create a server to respond to the HTTP2 requests -// const client = http2.connect(url, {}); -// client.on("error", (err) => console.error(err)); - -// const req = client.request({ ":method": "POST", ":path": "/" }, { -// waitForTrailers: true, -// }); - -// let receivedTrailers; -// let receivedHeaders; -// let receivedData = ""; - -// req.on("response", (headers, _flags) => { -// receivedHeaders = headers; -// }); - -// req.write("hello"); -// req.setEncoding("utf8"); - -// req.on("wantTrailers", () => { -// req.sendTrailers({ foo: "bar" }); -// }); - -// req.on("trailers", (trailers, _flags) => { -// receivedTrailers = trailers; -// }); - -// req.on("data", (chunk) => { -// receivedData += chunk; -// }); -// req.end(); - -// const { promise, resolve } = Promise.withResolvers(); -// setTimeout(() => { -// try { -// client.close(); -// } catch (_) { -// // pass -// } -// resolve(); -// }, 2000); - -// await promise; -// assertEquals(receivedHeaders, { ":status": 200 }); -// assertEquals(receivedData, "hello world\n"); - -// assertEquals(receivedTrailers, { -// "abc": "def", -// "opr": "stv", -// "foo": "bar", -// }); -// }); -// } - -// Deno.test(`[node/http2 client createConnection]`, { -// ignore: Deno.build.os === "windows", -// }, async () => { -// const url = "http://127.0.0.1:4246"; -// const createConnDeferred = Promise.withResolvers(); -// // Create a server to respond to the HTTP2 requests -// const client = http2.connect(url, { -// createConnection() { -// const socket = net.connect({ host: "127.0.0.1", port: 4246 }); - -// socket.on("connect", () => { -// createConnDeferred.resolve(); -// }); - -// return socket; -// }, -// }); -// client.on("error", (err) => console.error(err)); - -// const req = client.request({ ":method": "POST", ":path": "/" }); - -// let receivedData = ""; - -// req.write("hello"); -// req.setEncoding("utf8"); - -// req.on("data", (chunk) => { -// receivedData += chunk; -// }); -// req.end(); - -// const endPromise = Promise.withResolvers(); -// setTimeout(() => { -// try { -// client.close(); -// } catch (_) { -// // pass -// } -// endPromise.resolve(); -// }, 2000); - -// await createConnDeferred.promise; -// await endPromise.promise; -// assertEquals(receivedData, "hello world\n"); -// }); - -// Deno.test("[node/http2 client GET https://www.example.com]", async () => { -// const clientSession = http2.connect("https://www.example.com"); -// const req = clientSession.request({ -// ":method": "GET", -// ":path": "/", -// }); -// let headers = {}; -// let status: number | undefined = 0; -// let chunk = new Uint8Array(); -// const endPromise = Promise.withResolvers(); -// req.on("response", (h) => { -// status = h[":status"]; -// headers = h; -// }); -// req.on("data", (c) => { -// chunk = c; -// }); -// req.on("end", () => { -// clientSession.close(); -// req.close(); -// endPromise.resolve(); -// }); -// req.end(); -// await endPromise.promise; -// assert(Object.keys(headers).length > 0); -// assertEquals(status, 200); -// assert(chunk.length > 0); -// }); - -// Deno.test("[node/http2.createServer()]", { -// // TODO(satyarohith): enable the test on windows. -// ignore: Deno.build.os === "windows", -// }, async () => { -// const server = http2.createServer((_req, res) => { -// res.setHeader("Content-Type", "text/html"); -// res.setHeader("X-Foo", "bar"); -// res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" }); -// res.write("Hello, World!"); -// res.end(); -// }); -// server.listen(0); -// const port = ( server.address()).port; -// const endpoint = `http://localhost:${port}`; - -// const response = await curlRequest([ -// endpoint, -// "--http2-prior-knowledge", -// ]); -// assertEquals(response, "Hello, World!"); -// server.close(); -// // Wait to avoid leaking the timer from here -// // https://github.com/denoland/deno/blob/749b6e45e58ac87188027f79fe403d130f86bd73/ext/node/polyfills/net.ts#L2396-L2402 -// // Issue: https://github.com/denoland/deno/issues/22764 -// await new Promise((resolve) => server.on("close", resolve)); -// }); - - -Deno.test("[node/http2 client] write buffer on request stream works", async () => { - const url = "https://localhost:5545"; +for (const url of ["http://127.0.0.1:4246", "https://127.0.0.1:4247"]) { + Deno.test(`[node/http2 client] ${url}`, { + ignore: Deno.build.os === "windows", + }, async () => { + // Create a server to respond to the HTTP2 requests + const client = http2.connect(url, {}); + client.on("error", (err) => console.error(err)); + + const req = client.request({ ":method": "POST", ":path": "/" }, { + waitForTrailers: true, + }); + + let receivedTrailers; + let receivedHeaders; + let receivedData = ""; + + req.on("response", (headers, _flags) => { + receivedHeaders = headers; + }); + + req.write("hello"); + req.setEncoding("utf8"); + + req.on("wantTrailers", () => { + req.sendTrailers({ foo: "bar" }); + }); + + req.on("trailers", (trailers, _flags) => { + receivedTrailers = trailers; + }); + + req.on("data", (chunk) => { + receivedData += chunk; + }); + req.end(); + + const { promise, resolve } = Promise.withResolvers(); + setTimeout(() => { + try { + client.close(); + } catch (_) { + // pass + } + resolve(); + }, 2000); + + await promise; + assertEquals(receivedHeaders, { ":status": 200 }); + assertEquals(receivedData, "hello world\n"); + + assertEquals(receivedTrailers, { + "abc": "def", + "opr": "stv", + "foo": "bar", + }); + }); +} + +Deno.test(`[node/http2 client createConnection]`, { + ignore: Deno.build.os === "windows", +}, async () => { + const url = "http://127.0.0.1:4246"; + const createConnDeferred = Promise.withResolvers(); // Create a server to respond to the HTTP2 requests - const client = http2.connect(url) + const client = http2.connect(url, { + createConnection() { + const socket = net.connect({ host: "127.0.0.1", port: 4246 }); + + socket.on("connect", () => { + createConnDeferred.resolve(); + }); + + return socket; + }, + }); + client.on("error", (err) => console.error(err)); + + const req = client.request({ ":method": "POST", ":path": "/" }); + + let receivedData = ""; + + req.write("hello"); + req.setEncoding("utf8"); + + req.on("data", (chunk) => { + receivedData += chunk; + }); + req.end(); + + const endPromise = Promise.withResolvers(); + setTimeout(() => { + try { + client.close(); + } catch (_) { + // pass + } + endPromise.resolve(); + }, 2000); + + await createConnDeferred.promise; + await endPromise.promise; + assertEquals(receivedData, "hello world\n"); +}); + +Deno.test("[node/http2 client GET https://www.example.com]", async () => { + const clientSession = http2.connect("https://www.example.com"); + const req = clientSession.request({ + ":method": "GET", + ":path": "/", + }); + let headers = {}; + let status: number | undefined = 0; + let chunk = new Uint8Array(); + const endPromise = Promise.withResolvers(); + req.on("response", (h) => { + status = h[":status"]; + headers = h; + }); + req.on("data", (c) => { + chunk = c; + }); + req.on("end", () => { + clientSession.close(); + req.close(); + endPromise.resolve(); + }); + req.end(); + await endPromise.promise; + assert(Object.keys(headers).length > 0); + assertEquals(status, 200); + assert(chunk.length > 0); +}); + +Deno.test("[node/http2.createServer()]", { + // TODO(satyarohith): enable the test on windows. + ignore: Deno.build.os === "windows", +}, async () => { + const server = http2.createServer((_req, res) => { + res.setHeader("Content-Type", "text/html"); + res.setHeader("X-Foo", "bar"); + res.writeHead(200, { "Content-Type": "text/plain; charset=utf-8" }); + res.write("Hello, World!"); + res.end(); + }); + server.listen(0); + const port = ( server.address()).port; + const endpoint = `http://localhost:${port}`; + + const response = await curlRequest([ + endpoint, + "--http2-prior-knowledge", + ]); + assertEquals(response, "Hello, World!"); + server.close(); + // Wait to avoid leaking the timer from here + // https://github.com/denoland/deno/blob/749b6e45e58ac87188027f79fe403d130f86bd73/ext/node/polyfills/net.ts#L2396-L2402 + // Issue: https://github.com/denoland/deno/issues/22764 + await new Promise((resolve) => server.on("close", resolve)); +}); + +Deno.test("[node/http2 client] write image buffer on request stream works", async () => { + const url = "https://localhost:5545"; + const client = http2.connect(url); client.on("error", (err) => console.error(err)); const imagePath = join(import.meta.dirname!, "testdata", "green.jpg"); - console.log({ imagePath }) const buffer = await readFile(imagePath); - console.log({ bufferLength: buffer.length }) - // const imageLength = buffer.length; - // console.log({ imageLength }); const req = client.request({ ":method": "POST", ":path": "/echo_server" }); - // req.write(new Uint8Array([1, 2, 3, 4]), (err) => console.error("write cb", err)); - req.write(buffer, (err) => console.error("write cb", err)); + req.write(buffer, (err) => { + if (err) throw err; + }); - let chunks: Buffer; + let receivedData: Buffer; req.on("data", (chunk) => { - console.log("chunk receivedData", chunk); - // receivedData = Buffer.concat([receivedData, chunk]); - chunks = chunk; + if (!receivedData) { + receivedData = chunk; + } else { + receivedData = Buffer.concat([receivedData, chunk]); + } }); req.end(); @@ -206,8 +201,5 @@ Deno.test("[node/http2 client] write buffer on request stream works", async () = }, 2000); await endPromise.promise; - console.log("compare", buffer.compare(chunks!) === 0, buffer.length, chunks!.length) - // console.log("receivedData", receivedData); - // const expectedBuffer = fs.readFileSync("/Users/sr/c/denoland/deno/cat_dog.webp"); - assertEquals(chunks!, buffer); + assertEquals(receivedData!, buffer); });