aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/js/node/http.ts19
-rw-r--r--src/js/out/modules/node/http.js11
-rw-r--r--test/js/node/http/node-http.test.ts33
3 files changed, 60 insertions, 3 deletions
diff --git a/src/js/node/http.ts b/src/js/node/http.ts
index a745f9b32..42388b32e 100644
--- a/src/js/node/http.ts
+++ b/src/js/node/http.ts
@@ -957,6 +957,7 @@ export class OutgoingMessage extends Writable {
}
}
+let OriginalWriteHeadFn, OriginalImplicitHeadFn;
export class ServerResponse extends Writable {
declare _writableState: any;
@@ -989,9 +990,11 @@ export class ServerResponse extends Writable {
_removedContLen = false;
#deferred: (() => void) | undefined = undefined;
#finished = false;
-
// Express "compress" package uses this
- _implicitHeader() {}
+ _implicitHeader() {
+ // @ts-ignore
+ this.writeHead(this.statusCode);
+ }
_write(chunk, encoding, callback) {
if (!this.#firstWrite && !this.headersSent) {
@@ -1053,11 +1056,20 @@ export class ServerResponse extends Writable {
);
}
+ #drainHeadersIfObservable() {
+ if (this._implicitHeader === OriginalImplicitHeadFn && this.writeHead === OriginalWriteHeadFn) {
+ return;
+ }
+
+ this._implicitHeader();
+ }
+
_final(callback) {
if (!this.headersSent) {
var data = this.#firstWrite || "";
this.#firstWrite = undefined;
this.#finished = true;
+ this.#drainHeadersIfObservable();
this._reply(
new Response(data, {
headers: this.#headers,
@@ -1176,6 +1188,9 @@ export class ServerResponse extends Writable {
}
}
+OriginalWriteHeadFn = ServerResponse.prototype.writeHead;
+OriginalImplicitHeadFn = ServerResponse.prototype._implicitHeader;
+
export class ClientRequest extends OutgoingMessage {
#timeout;
#res: IncomingMessage | null = null;
diff --git a/src/js/out/modules/node/http.js b/src/js/out/modules/node/http.js
index 13ee7fded..d0937a945 100644
--- a/src/js/out/modules/node/http.js
+++ b/src/js/out/modules/node/http.js
@@ -626,6 +626,7 @@ class OutgoingMessage extends Writable {
return this;
}
}
+var OriginalWriteHeadFn, OriginalImplicitHeadFn;
class ServerResponse extends Writable {
constructor({ req, reply }) {
@@ -648,6 +649,7 @@ class ServerResponse extends Writable {
#deferred = void 0;
#finished = !1;
_implicitHeader() {
+ this.writeHead(this.statusCode);
}
_write(chunk, encoding, callback) {
if (!this.#firstWrite && !this.headersSent) {
@@ -691,10 +693,15 @@ class ServerResponse extends Writable {
statusText: this.statusMessage ?? STATUS_CODES[this.statusCode]
}));
}
+ #drainHeadersIfObservable() {
+ if (this._implicitHeader === OriginalImplicitHeadFn && this.writeHead === OriginalWriteHeadFn)
+ return;
+ this._implicitHeader();
+ }
_final(callback) {
if (!this.headersSent) {
var data = this.#firstWrite || "";
- this.#firstWrite = void 0, this.#finished = !0, this._reply(new Response(data, {
+ this.#firstWrite = void 0, this.#finished = !0, this.#drainHeadersIfObservable(), this._reply(new Response(data, {
headers: this.#headers,
status: this.statusCode,
statusText: this.statusMessage ?? STATUS_CODES[this.statusCode]
@@ -780,6 +787,8 @@ class ServerResponse extends Writable {
return _writeHead(statusCode, statusMessage, headers, this), this;
}
}
+OriginalWriteHeadFn = ServerResponse.prototype.writeHead;
+OriginalImplicitHeadFn = ServerResponse.prototype._implicitHeader;
class ClientRequest extends OutgoingMessage {
#timeout;
diff --git a/test/js/node/http/node-http.test.ts b/test/js/node/http/node-http.test.ts
index 3e7da9d34..0e7b3ca13 100644
--- a/test/js/node/http/node-http.test.ts
+++ b/test/js/node/http/node-http.test.ts
@@ -146,6 +146,29 @@ describe("node:http", () => {
res.end("Path correct!\n");
return;
}
+ if (reqUrl.pathname === "/customWriteHead") {
+ function createWriteHead(prevWriteHead, listener) {
+ let fired = false;
+ return function writeHead() {
+ if (!fired) {
+ fired = true;
+ listener.call(this);
+ }
+ return prevWriteHead.apply(this, arguments);
+ };
+ }
+
+ function addPoweredBy() {
+ if (!this.getHeader("X-Powered-By")) {
+ this.setHeader("X-Powered-By", "Bun");
+ }
+ }
+
+ res.writeHead = createWriteHead(res.writeHead, addPoweredBy);
+ res.setHeader("Content-Type", "text/plain");
+ res.end("Hello World");
+ return;
+ }
}
res.writeHead(200, { "Content-Type": "text/plain" });
@@ -507,6 +530,16 @@ describe("node:http", () => {
req.end();
});
});
+ it("reassign writeHead method, issue#3585", done => {
+ runTest(done, (server, serverPort, done) => {
+ const req = request(`http://localhost:${serverPort}/customWriteHead`, res => {
+ expect(res.headers["content-type"]).toBe("text/plain");
+ expect(res.headers["x-powered-by"]).toBe("Bun");
+ done();
+ });
+ req.end();
+ });
+ });
});
describe("signal", () => {