Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 22 additions & 13 deletions src/runtime/server/NodeHTTPResponse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1920,21 +1920,30 @@ impl NodeHTTPResponse {
let mut string_or_buffer = crate::node::StringOrBuffer::EMPTY;
if !input_value.is_undefined_or_null() {
let mut encoding = crate::node::Encoding::Utf8;
if !encoding_value.is_undefined_or_null() {
if !encoding_value.is_string() {
return Err(global_object.throw_invalid_argument_type_value(
b"encoding",
b"string",
encoding_value,
));
}

encoding = match crate::node::Encoding::from_js(encoding_value, global_object)? {
// Like Writable.prototype.write: a falsy encoding means the default.
if !encoding_value.is_falsey() {
Comment thread
robobun marked this conversation as resolved.
let known = if encoding_value.is_string() {
crate::node::Encoding::from_js(encoding_value, global_object)?
Comment thread
robobun marked this conversation as resolved.
} else {
None
};
encoding = match known {
Some(e) => e,
None => {
return Err(
global_object.throw_invalid_arguments(format_args!("Invalid encoding"))
);
let name = if encoding_value.is_string() {
encoding_value.to_bun_string(global_object)?
} else {
JSGlobalObject::inspect_for_error_message(
global_object,
encoding_value,
)?
};
return Err(global_object
.err(
ErrorCode::UNKNOWN_ENCODING,
format_args!("Unknown encoding: {}", name),
)
.throw());
}
};
}
Expand Down
48 changes: 48 additions & 0 deletions test/js/node/http/node-http.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -329,6 +329,54 @@ describe("node:http", () => {
"test": "test",
});
});

// Node's Writable.prototype.write uses the default encoding for a falsy
// encoding argument, so res.write(chunk, "") and res.end(chunk, "") write utf8.
test.each(["write", "end"])("res.%s accepts an empty-string encoding (#43370)", async method => {
const body = "héllo wörld ✓";
await using server = http.createServer((req, res) => {
try {
if (method === "write") {
res.write(body, "");
res.end();
} else {
res.end(body, "");
}
} catch (e: any) {
res.statusCode = 500;
res.end(`${e.code}: ${e.message}`);
}
});
await once(server.listen(0, "127.0.0.1"), "listening");
const { port } = server.address() as AddressInfo;

const response = await fetch(`http://127.0.0.1:${port}/`);
expect(await response.text()).toBe(body);
expect(response.status).toBe(200);
});

test.each(["write", "end"])("res.%s throws ERR_UNKNOWN_ENCODING for an unknown encoding", async method => {
const errors: string[] = [];
await using server = http.createServer((req, res) => {
for (const encoding of ["bogus", 123, {}]) {
try {
res[method]("x", encoding);
} catch (e: any) {
errors.push(`${e.code}: ${e.message}`);
}
}
res.end();
});
await once(server.listen(0, "127.0.0.1"), "listening");
const { port } = server.address() as AddressInfo;

await fetch(`http://127.0.0.1:${port}/`);
expect(errors).toEqual([
"ERR_UNKNOWN_ENCODING: Unknown encoding: bogus",
"ERR_UNKNOWN_ENCODING: Unknown encoding: 123",
"ERR_UNKNOWN_ENCODING: Unknown encoding: {}",
]);
});
});

describe("request", () => {
Expand Down
Loading