mirror of
https://github.com/oven-sh/bun
synced 2026-02-02 15:08:46 +00:00
fix(sql): auto-populate TLS serverName when using tls: true option
When using Bun.SQL with individual connection options and tls: true, the SNI hostname was not sent during the TLS handshake. This caused connections to fail on servers that require SNI (like Neon). The issue was that the code to auto-populate tls.serverName from the hostname ran before sslMode was promoted from disable to prefer. This fix swaps the order of these two operations so sslMode is promoted first, allowing serverName to be properly set. Fixes #26369 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -838,6 +838,10 @@ function parseOptions(
|
||||
}
|
||||
}
|
||||
|
||||
if (tls && sslMode === SSLMode.disable) {
|
||||
sslMode = SSLMode.prefer;
|
||||
}
|
||||
|
||||
if (sslMode !== SSLMode.disable && !tls?.serverName) {
|
||||
if (hostname) {
|
||||
tls = { ...tls, serverName: hostname };
|
||||
@@ -846,10 +850,6 @@ function parseOptions(
|
||||
}
|
||||
}
|
||||
|
||||
if (tls && sslMode === SSLMode.disable) {
|
||||
sslMode = SSLMode.prefer;
|
||||
}
|
||||
|
||||
port = Number(port);
|
||||
|
||||
if (!Number.isSafeInteger(port) || port < 1 || port > 65535) {
|
||||
|
||||
106
test/regression/issue/26369.test.ts
Normal file
106
test/regression/issue/26369.test.ts
Normal file
@@ -0,0 +1,106 @@
|
||||
import { SQL } from "bun";
|
||||
import { describe, expect, test } from "bun:test";
|
||||
|
||||
describe("Issue #26369 - SNI hostname not sent when using tls: true with individual connection options", () => {
|
||||
test("tls: true with host option should auto-populate serverName", () => {
|
||||
const sql = new SQL({
|
||||
host: "example-host.neon.tech",
|
||||
username: "user",
|
||||
password: "pass",
|
||||
database: "db",
|
||||
tls: true,
|
||||
adapter: "postgres",
|
||||
});
|
||||
|
||||
// Verify serverName is automatically set from the hostname
|
||||
expect(sql.options.tls).toEqual({ serverName: "example-host.neon.tech" });
|
||||
|
||||
sql.close();
|
||||
});
|
||||
|
||||
test("tls: true with hostname option should auto-populate serverName", () => {
|
||||
const sql = new SQL({
|
||||
hostname: "example-host.neon.tech",
|
||||
username: "user",
|
||||
password: "pass",
|
||||
database: "db",
|
||||
tls: true,
|
||||
adapter: "postgres",
|
||||
});
|
||||
|
||||
// Verify serverName is automatically set from the hostname
|
||||
expect(sql.options.tls).toEqual({ serverName: "example-host.neon.tech" });
|
||||
|
||||
sql.close();
|
||||
});
|
||||
|
||||
test("tls with explicit serverName should preserve it", () => {
|
||||
const sql = new SQL({
|
||||
host: "example-host.neon.tech",
|
||||
username: "user",
|
||||
password: "pass",
|
||||
database: "db",
|
||||
tls: { serverName: "custom-server-name.example.com" },
|
||||
adapter: "postgres",
|
||||
});
|
||||
|
||||
// Verify explicit serverName is preserved
|
||||
expect(sql.options.tls).toEqual({ serverName: "custom-server-name.example.com" });
|
||||
|
||||
sql.close();
|
||||
});
|
||||
|
||||
test("URL with sslmode=require should auto-populate serverName", () => {
|
||||
const sql = new SQL("postgresql://user:pass@example-host.neon.tech/db?sslmode=require");
|
||||
|
||||
// Verify serverName is automatically set from the URL hostname
|
||||
expect(sql.options.tls).toEqual({ serverName: "example-host.neon.tech" });
|
||||
|
||||
sql.close();
|
||||
});
|
||||
|
||||
test("URL without sslmode but with tls: true option should auto-populate serverName", () => {
|
||||
const sql = new SQL("postgresql://user:pass@example-host.neon.tech/db", {
|
||||
tls: true,
|
||||
});
|
||||
|
||||
// Verify serverName is automatically set from the URL hostname
|
||||
expect(sql.options.tls).toEqual({ serverName: "example-host.neon.tech" });
|
||||
|
||||
sql.close();
|
||||
});
|
||||
|
||||
test("tls object with other properties should also get serverName", () => {
|
||||
const sql = new SQL({
|
||||
host: "example-host.neon.tech",
|
||||
username: "user",
|
||||
password: "pass",
|
||||
database: "db",
|
||||
tls: { rejectUnauthorized: false },
|
||||
adapter: "postgres",
|
||||
});
|
||||
|
||||
// Verify serverName is added alongside existing tls properties
|
||||
expect(sql.options.tls).toEqual({
|
||||
rejectUnauthorized: false,
|
||||
serverName: "example-host.neon.tech",
|
||||
});
|
||||
|
||||
sql.close();
|
||||
});
|
||||
|
||||
test("no tls option should not set tls in options", () => {
|
||||
const sql = new SQL({
|
||||
host: "example-host.neon.tech",
|
||||
username: "user",
|
||||
password: "pass",
|
||||
database: "db",
|
||||
adapter: "postgres",
|
||||
});
|
||||
|
||||
// Verify tls is not set when not explicitly enabled
|
||||
expect(sql.options.tls).toBeUndefined();
|
||||
|
||||
sql.close();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user