Skip to content

Commit 90620b6

Browse files
committed
[SEA-NodeJS] feat(kernel): support the explicit proxy ConnectionOption on the kernel backend
Map the public Thrift-shaped `ConnectionOptions.proxy` (`{protocol, host, port, auth}`) onto the kernel napi binding's `proxy?: string`, so the SAME proxy connection option that works on the Thrift backend now also routes kernel/SEA traffic through a proxy. `buildKernelProxyOptions` composes `protocol://[user:pass@]host:port`, percent-encoding any `auth.{username,password}` into the URL userinfo so credentials with reserved characters survive; the kernel parses the userinfo off and applies it as proxy basic-auth. Wired into `buildKernelConnectionOptions` alongside the TLS / HTTP option builders. The regenerated napi contract (`native/kernel/index.d.ts`) carries the new `proxy?: string` and `socketTimeoutMs?: number` fields exposed by the kernel PR (databricks/databricks-sql-kernel#129). Note: env-var proxying (`HTTPS_PROXY` / `HTTP_PROXY` / `NO_PROXY`) already worked on the kernel backend (reqwest honours it natively); this adds the *programmatic* path for callers who cannot set process env vars. Verified end-to-end via mitmproxy against a live serverless warehouse: explicit `proxy` option (no env var) routes all SEA calls through the proxy; a dead proxy port fails the connection (proving the proxy is used). Co-authored-by: Isaac
1 parent 26be3be commit 90620b6

2 files changed

Lines changed: 72 additions & 3 deletions

File tree

lib/kernel/KernelAuth.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -173,9 +173,22 @@ export interface KernelHttpOptions {
173173
customHeaders?: Array<{ name: string; value: string }>;
174174
}
175175

176+
/**
177+
* HTTP(S) proxy forwarded to the napi binding's `ConnectionOptions.proxy`
178+
* (kernel `ProxyConfig.url`). The public `ConnectionOptions.proxy` is the
179+
* Thrift-shaped `{protocol, host, port, auth}`; `buildKernelProxyOptions`
180+
* composes a single proxy URL string (with any basic-auth credentials
181+
* percent-encoded into the `userinfo`) so the SAME connection option works
182+
* on both backends. The napi contract takes a flat `proxy?: string`.
183+
*/
184+
export interface KernelProxyOptions {
185+
proxy?: string;
186+
}
187+
176188
export type KernelNativeConnectionOptions = KernelSessionDefaults &
177189
KernelTlsOptions &
178190
KernelHttpOptions &
191+
KernelProxyOptions &
179192
(
180193
| {
181194
hostName: string;
@@ -492,6 +505,29 @@ export function buildKernelRetryOptions(config: {
492505
return out;
493506
}
494507

508+
/**
509+
* Map the public `ConnectionOptions.proxy` (`{protocol, host, port, auth}` —
510+
* the same shape the Thrift backend accepts) onto the kernel's napi
511+
* `proxy?: string`. Composes `protocol://[user:pass@]host:port`, percent-
512+
* encoding any `auth.{username,password}` into the URL `userinfo` so
513+
* credentials containing reserved characters (`@`, `:`, `/`) survive intact —
514+
* the kernel parses the userinfo off and applies it as basic-auth. The kernel
515+
* accepts only `http://` / `https://`; a SOCKS protocol surfaces a clear
516+
* kernel error at connect (reqwest SOCKS support is not compiled in).
517+
*/
518+
export function buildKernelProxyOptions(options: ConnectionOptions): KernelProxyOptions {
519+
const { proxy } = options;
520+
if (!proxy) {
521+
return {};
522+
}
523+
const { username, password } = proxy.auth ?? {};
524+
const userinfo =
525+
username !== undefined ? `${encodeURIComponent(username)}:${encodeURIComponent(password ?? '')}@` : '';
526+
return {
527+
proxy: `${proxy.protocol}://${userinfo}${proxy.host}:${proxy.port}`,
528+
};
529+
}
530+
495531
export function buildKernelConnectionOptions(options: ConnectionOptions): KernelNativeConnectionOptions {
496532
const { authType } = options as { authType?: string };
497533

@@ -501,7 +537,8 @@ export function buildKernelConnectionOptions(options: ConnectionOptions): Kernel
501537
intervalsAsString: boolean;
502538
maxConnections?: number;
503539
} & KernelTlsOptions &
504-
KernelHttpOptions = {
540+
KernelHttpOptions &
541+
KernelProxyOptions = {
505542
hostName: options.host,
506543
httpPath: prependSlash(options.path),
507544
// Match the NodeJS Thrift driver, which surfaces INTERVAL columns as
@@ -517,6 +554,8 @@ export function buildKernelConnectionOptions(options: ConnectionOptions): Kernel
517554
...buildKernelTlsOptions(options),
518555
// HTTP headers (caller `customHeaders` + composed `User-Agent`).
519556
...buildKernelHttpOptions(options),
557+
// HTTP(S) proxy — the same `ConnectionOptions.proxy` the Thrift path uses.
558+
...buildKernelProxyOptions(options),
520559
};
521560

522561
// kernel-only pool sizing; read via cast to match how this function reads the

native/kernel/index.d.ts

Lines changed: 32 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)