@openclaw/proxyline 0.3.1 → 0.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.2 - 2026-05-17
4
+
5
+ - Fixed managed Undici proxy dispatchers so HTTPS proxy endpoints addressed by IP do not send invalid IP-literal SNI.
6
+
3
7
  ## 0.3.1 - 2026-05-16
4
8
 
5
9
  - Fixed `withBypass()` to scope temporary bypasses to the calling async context instead of process-wide state.
@@ -1 +1 @@
1
- {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAIV,eAAe,EACf,gBAAgB,EAIjB,MAAM,YAAY,CAAC;AA0tBpB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAgI3E;AAED,eAAO,MAAM,kBAAkB,yBAAmB,CAAC"}
1
+ {"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAsCA,OAAO,KAAK,EAIV,eAAe,EACf,gBAAgB,EAIjB,MAAM,YAAY,CAAC;AAqwBpB,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,gBAAgB,GAAG,eAAe,CAgI3E;AAED,eAAO,MAAM,kBAAkB,yBAAmB,CAAC"}
package/dist/runtime.js CHANGED
@@ -1,7 +1,8 @@
1
1
  import http from "node:http";
2
2
  import https from "node:https";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
- import { Agent as UndiciAgent, Dispatcher, FormData as UndiciFormData, Headers as UndiciHeaders, Request as UndiciRequest, Response as UndiciResponse, errors as undiciErrors, fetch as undiciFetch, getGlobalDispatcher, ProxyAgent as UndiciProxyAgent, setGlobalDispatcher, } from "undici";
4
+ import net from "node:net";
5
+ import { Agent as UndiciAgent, Dispatcher, FormData as UndiciFormData, Headers as UndiciHeaders, Pool as UndiciPool, Request as UndiciRequest, Response as UndiciResponse, errors as undiciErrors, fetch as undiciFetch, getGlobalDispatcher, ProxyAgent as UndiciProxyAgent, setGlobalDispatcher, } from "undici";
5
6
  import { createAmbientProxyResolver, EMPTY_PROXY_ENV, resolveAmbientProxyForUrl, readProxyEnv, } from "./env.js";
6
7
  import { bindNodeHttpMethod, createDirectNodeAgent, createNodeProxyAgent, } from "./node-http.js";
7
8
  import { formatUrl, ProxylineError, redactProxyUrl, resolveProxyTlsCa, } from "./shared.js";
@@ -272,10 +273,40 @@ function resolveUndiciBaseOptions(options) {
272
273
  function createUndiciAgent(options) {
273
274
  return new UndiciAgent(resolveUndiciBaseOptions(options));
274
275
  }
276
+ function isObjectRecord(value) {
277
+ return typeof value === "object" && value !== null && !Array.isArray(value);
278
+ }
279
+ function stripIpServernameFromConnectOptions(options) {
280
+ if (!isObjectRecord(options) || typeof options.servername !== "string") {
281
+ return options;
282
+ }
283
+ const servername = options.servername.replace(/^\[|\]$/g, "");
284
+ if (net.isIP(servername) === 0) {
285
+ return options;
286
+ }
287
+ const next = { ...options };
288
+ delete next.servername;
289
+ return next;
290
+ }
291
+ function stripIpServernameFromConnect(connect) {
292
+ if (typeof connect !== "function") {
293
+ return connect;
294
+ }
295
+ return (options, callback) => connect(stripIpServernameFromConnectOptions(options), callback);
296
+ }
297
+ function createProxyClientFactory() {
298
+ return (origin, options) => {
299
+ const clientOptions = isObjectRecord(options)
300
+ ? { ...options, connect: stripIpServernameFromConnect(options.connect) }
301
+ : options;
302
+ return new UndiciPool(origin, clientOptions);
303
+ };
304
+ }
275
305
  function createUndiciProxyAgent(proxyUrl, options) {
276
306
  return new UndiciProxyAgent({
277
307
  ...resolveUndiciBaseOptions(options.undici),
278
308
  uri: proxyUrl,
309
+ clientFactory: createProxyClientFactory(),
279
310
  ...(options.proxyCa !== undefined ? { proxyTls: { ca: options.proxyCa } } : {}),
280
311
  });
281
312
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openclaw/proxyline",
3
- "version": "0.3.1",
3
+ "version": "0.3.2",
4
4
  "description": "Process-global proxy routing for Node.js.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/runtime.ts CHANGED
@@ -1,11 +1,13 @@
1
1
  import http from "node:http";
2
2
  import https from "node:https";
3
3
  import { AsyncLocalStorage } from "node:async_hooks";
4
+ import net from "node:net";
4
5
  import {
5
6
  Agent as UndiciAgent,
6
7
  Dispatcher,
7
8
  FormData as UndiciFormData,
8
9
  Headers as UndiciHeaders,
10
+ Pool as UndiciPool,
9
11
  Request as UndiciRequest,
10
12
  Response as UndiciResponse,
11
13
  errors as undiciErrors,
@@ -389,6 +391,11 @@ type UndiciDispatcherOptions = Readonly<{
389
391
  proxyCa: string | undefined;
390
392
  undici: ProxylineUndiciOptions | undefined;
391
393
  }>;
394
+ type UndiciProxyAgentOptions = Exclude<ConstructorParameters<typeof UndiciProxyAgent>[0], string | URL>;
395
+ type UndiciProxyClientFactory = NonNullable<
396
+ UndiciProxyAgentOptions["clientFactory"]
397
+ >;
398
+ type UnknownFunction = (...args: unknown[]) => unknown;
392
399
 
393
400
  function finiteNonNegativeInteger(value: number | undefined): number | undefined {
394
401
  return typeof value === "number" && Number.isFinite(value) && value >= 0
@@ -434,6 +441,43 @@ function createUndiciAgent(options: ProxylineUndiciOptions | undefined): UndiciA
434
441
  return new UndiciAgent(resolveUndiciBaseOptions(options));
435
442
  }
436
443
 
444
+ function isObjectRecord(value: unknown): value is Record<string, unknown> {
445
+ return typeof value === "object" && value !== null && !Array.isArray(value);
446
+ }
447
+
448
+ function stripIpServernameFromConnectOptions(options: unknown): unknown {
449
+ if (!isObjectRecord(options) || typeof options.servername !== "string") {
450
+ return options;
451
+ }
452
+ const servername = options.servername.replace(/^\[|\]$/g, "");
453
+ if (net.isIP(servername) === 0) {
454
+ return options;
455
+ }
456
+ const next = { ...options };
457
+ delete next.servername;
458
+ return next;
459
+ }
460
+
461
+ function stripIpServernameFromConnect(connect: unknown): unknown {
462
+ if (typeof connect !== "function") {
463
+ return connect;
464
+ }
465
+ return (options: unknown, callback: unknown): unknown =>
466
+ (connect as UnknownFunction)(stripIpServernameFromConnectOptions(options), callback);
467
+ }
468
+
469
+ function createProxyClientFactory(): UndiciProxyClientFactory {
470
+ return (origin: URL, options: object): Dispatcher => {
471
+ const clientOptions = isObjectRecord(options)
472
+ ? { ...options, connect: stripIpServernameFromConnect(options.connect) }
473
+ : options;
474
+ return new UndiciPool(
475
+ origin,
476
+ clientOptions as ConstructorParameters<typeof UndiciPool>[1],
477
+ );
478
+ };
479
+ }
480
+
437
481
  function createUndiciProxyAgent(
438
482
  proxyUrl: string,
439
483
  options: UndiciDispatcherOptions,
@@ -441,6 +485,7 @@ function createUndiciProxyAgent(
441
485
  return new UndiciProxyAgent({
442
486
  ...resolveUndiciBaseOptions(options.undici),
443
487
  uri: proxyUrl,
488
+ clientFactory: createProxyClientFactory(),
444
489
  ...(options.proxyCa !== undefined ? { proxyTls: { ca: options.proxyCa } } : {}),
445
490
  } as ConstructorParameters<typeof UndiciProxyAgent>[0]);
446
491
  }