@percy/sdk-utils 1.31.3-beta.5 → 1.31.3-beta.6

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.
Files changed (2) hide show
  1. package/dist/proxy.js +27 -2
  2. package/package.json +2 -2
package/dist/proxy.js CHANGED
@@ -134,7 +134,32 @@ function stripQuotesAndSpaces(str) {
134
134
  // Returns the proxy URL for a set of request options
135
135
  function getProxy(options) {
136
136
  let proxyUrl = options.protocol === 'https:' && (process.env.https_proxy || process.env.HTTPS_PROXY) || process.env.http_proxy || process.env.HTTP_PROXY;
137
- let shouldProxy = !!proxyUrl && !hostnameMatches(stripQuotesAndSpaces(process.env.no_proxy || process.env.NO_PROXY), href(options));
137
+
138
+ // Always exclude localhost/127.0.0.1 from proxying to prevent internal loops
139
+ //
140
+ // CRITICAL: Percy SDK communicates with percy-cli server via HTTP calls to localhost:5338
141
+ // When HTTP_PROXY is set, these internal communications would be routed through the proxy,
142
+ // creating a feedback loop that causes memory leaks and crashes:
143
+ //
144
+ // 1. SDK makes request to localhost:5338/percy/log (internal communication)
145
+ // 2. Request gets routed through external proxy due to HTTP_PROXY setting
146
+ // 3. Proxy forwards request back to localhost:5338 (adds latency + overhead)
147
+ // 4. Percy server processes request and generates internal logs/metrics
148
+ // 5. Those logs trigger MORE requests to localhost:5338/percy/log
149
+ // 6. Each new request also gets proxied, creating exponential growth
150
+ // 7. Eventually: JavaScript heap exhaustion and process crash
151
+ //
152
+ // By excluding localhost by default, we ensure:
153
+ // - External requests (percy.io, etc.) go through proxy as intended
154
+ // - Internal percy-cli ↔ sdk communications remain fast and direct
155
+ // - No risk of internal communication loops or memory leaks
156
+ //
157
+ // This follows standard industry practice - most proxy implementations
158
+ // (Docker, browsers, corporate proxies) exclude localhost by default.
159
+ let noProxyList = stripQuotesAndSpaces(process.env.no_proxy || process.env.NO_PROXY) || '';
160
+ const defaultNoProxy = 'localhost,127.0.0.1,::1,[::1]';
161
+ noProxyList = noProxyList ? `${noProxyList},${defaultNoProxy}` : defaultNoProxy;
162
+ let shouldProxy = !!proxyUrl && !hostnameMatches(noProxyList, href(options));
138
163
  if (proxyUrl && typeof proxyUrl === 'string') {
139
164
  proxyUrl = stripQuotesAndSpaces(proxyUrl);
140
165
  }
@@ -169,7 +194,7 @@ class ProxyHttpAgent extends _http.default.Agent {
169
194
  var _request$outputData;
170
195
  let proxy = getProxy(options);
171
196
  if (!proxy) return super.addRequest(request, options);
172
- (0, _logger.default)('sdk-utils:proxy').debug(`Proxying request: ${href(options)}`);
197
+ (0, _logger.default)('sdk-utils:proxy').debug(`Proxying request: ${href(options)} via ${proxy.host}:${proxy.port}`);
173
198
 
174
199
  // modify the request for proxying
175
200
  request.path = href(options);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@percy/sdk-utils",
3
- "version": "1.31.3-beta.5",
3
+ "version": "1.31.3-beta.6",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -54,5 +54,5 @@
54
54
  "dependencies": {
55
55
  "pac-proxy-agent": "^7.0.2"
56
56
  },
57
- "gitHead": "b029fc53f478818c5a34205d1ff3b22d7d4390af"
57
+ "gitHead": "ca15e75708a7d474d32e460265afb4bb07fd4110"
58
58
  }