Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 11ea830

Browse files
fix(aws-serverless): Take http_proxy into account when choosing useLayerExtension default (#17817)
The default setting for `useLayerExtension` now considers the `http_proxy` environment variable. When `http_proxy` is set, `useLayerExtension` will be off by default. If you use a `http_proxy` but would still like to make use of the Sentry Lambda extension, exempt `localhost` in a `no_proxy` environment variable. Fixes: #17804 <!-- CURSOR_SUMMARY --> --- > [!NOTE] > Disable `useLayerExtension` by default when `http_proxy` is set (unless `no_proxy` exempts localhost), add debug warnings, tests, and changelog entry. > > - **aws-serverless**: > - Consider proxy env vars when defaulting `useLayerExtension` in `packages/aws-serverless/src/init.ts`. > - New `shouldDisableLayerExtensionForProxy()` checks `http_proxy` and `no_proxy` (localhost exemptions). > - Update default: enable only if using Lambda layer, no custom tunnel, and no proxy interference. > - Add debug warnings when disabling due to proxy and when tunneling via extension. > - **Tests**: > - Expand `packages/aws-serverless/test/init.test.ts` to cover proxy/no_proxy scenarios, explicit overrides, and env cleanup. > - **Docs/Changelog**: > - Add Important Changes note explaining new default behavior and how to re-enable with `no_proxy` exemptions. > > <sup>Written by [Cursor Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit 53e333f. This will update automatically on new commits. Configure [here](https://cursor.com/dashboard?tab=bugbot).</sup> <!-- /CURSOR_SUMMARY -->
1 parent e966cdc commit 11ea830

File tree

3 files changed

+312
-2
lines changed

3 files changed

+312
-2
lines changed

‎CHANGELOG.md‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
- "You miss 100 percent of the chances you don't take. — Wayne Gretzky" — Michael Scott
66

7+
### Important Changes
8+
9+
- **fix(aws-serverless): Take `http_proxy` into account when choosing
10+
`useLayerExtension` default ([#17817](https://github.com/getsentry/sentry-javascript/pull/17817))**
11+
12+
The default setting for `useLayerExtension` now considers the `http_proxy` environment variable. When `http_proxy` is set, `useLayerExtension` will be off by default. If you use a `http_proxy` but would still like to make use of the Sentry Lambda extension, exempt `localhost` in a `no_proxy` environment variable.
13+
714
## 10.16.0
815

916
- feat(logs): Add internal `replay_is_buffering` flag ([#17752](https://github.com/getsentry/sentry-javascript/pull/17752))

‎packages/aws-serverless/src/init.ts‎

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,44 @@ import { getDefaultIntegrationsWithoutPerformance, initWithoutDefaultIntegration
55
import { DEBUG_BUILD } from './debug-build';
66
import { awsIntegration } from './integration/aws';
77
import { awsLambdaIntegration } from './integration/awslambda';
8+
9+
/**
10+
* Checks if proxy environment variables would interfere with the layer extension.
11+
* The layer extension uses localhost:9000, so we need to check if proxy settings would prevent this.
12+
*/
13+
function shouldDisableLayerExtensionForProxy(): boolean {
14+
const { http_proxy, no_proxy } = process.env;
15+
16+
// If no http proxy is configured, no interference (https_proxy doesn't affect HTTP requests)
17+
if (!http_proxy) {
18+
return false;
19+
}
20+
21+
// Check if localhost is exempted by no_proxy
22+
if (no_proxy) {
23+
const exemptions = no_proxy.split(',').map(exemption => exemption.trim().toLowerCase());
24+
25+
// Handle common localhost exemption patterns explicitly
26+
// If localhost is exempted, requests to the layer extension will not be proxied
27+
const localhostExemptions = ['*', 'localhost', '127.0.0.1', '::1'];
28+
if (exemptions.some(exemption => localhostExemptions.includes(exemption))) {
29+
return false;
30+
}
31+
}
32+
33+
// If http_proxy is set and no localhost exemption, it would interfere
34+
// The layer extension uses HTTP to localhost:9000, so only http_proxy matters
35+
if (http_proxy) {
36+
DEBUG_BUILD &&
37+
debug.log(
38+
'Disabling useLayerExtension due to http_proxy environment variable. Consider adding localhost to no_proxy to re-enable.',
39+
);
40+
return true;
41+
}
42+
43+
return false;
44+
}
45+
846
/**
947
* Get the default integrations for the AWSLambda SDK.
1048
*/
@@ -28,9 +66,11 @@ export interface AwsServerlessOptions extends NodeOptions {
2866
*/
2967
export function init(options: AwsServerlessOptions = {}): NodeClient | undefined {
3068
const sdkSource = getSDKSource();
69+
const proxyWouldInterfere = shouldDisableLayerExtensionForProxy();
70+
3171
const opts = {
3272
defaultIntegrations: getDefaultIntegrations(options),
33-
useLayerExtension: sdkSource === 'aws-lambda-layer' && !options.tunnel,
73+
useLayerExtension: sdkSource === 'aws-lambda-layer' && !options.tunnel&&!proxyWouldInterfere,
3474
...options,
3575
};
3676

@@ -48,6 +88,11 @@ export function init(options: AwsServerlessOptions = {}): NodeClient | undefined
4888
} else {
4989
DEBUG_BUILD && debug.warn('The Sentry Lambda extension is only supported when using the AWS Lambda layer.');
5090
}
91+
} else if (sdkSource === 'aws-lambda-layer' && proxyWouldInterfere) {
92+
DEBUG_BUILD &&
93+
debug.warn(
94+
'Sentry Lambda extension disabled due to proxy environment variables (http_proxy/https_proxy). Consider adding localhost to no_proxy to re-enable.',
95+
);
5196
}
5297

5398
applySdkMetadata(opts, 'aws-serverless', ['aws-serverless'], sdkSource);

‎packages/aws-serverless/test/init.test.ts‎

Lines changed: 259 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { getSDKSource } from '@sentry/core';
22
import { initWithoutDefaultIntegrations } from '@sentry/node';
3-
import { describe, expect, test, vi } from 'vitest';
3+
import { beforeEach,describe, expect, test, vi } from 'vitest';
44
import type { AwsServerlessOptions } from '../src/init';
55
import { init } from '../src/init';
66

@@ -18,6 +18,12 @@ const mockGetSDKSource = vi.mocked(getSDKSource);
1818
const mockInitWithoutDefaultIntegrations = vi.mocked(initWithoutDefaultIntegrations);
1919

2020
describe('init', () => {
21+
beforeEach(() => {
22+
// Clean up environment variables between tests
23+
delete process.env.http_proxy;
24+
delete process.env.no_proxy;
25+
});
26+
2127
describe('Lambda extension setup', () => {
2228
test('should preserve user-provided tunnel option when Lambda extension is enabled', () => {
2329
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
@@ -128,4 +134,256 @@ describe('init', () => {
128134
);
129135
});
130136
});
137+
138+
describe('proxy environment variables and layer extension', () => {
139+
test('should enable useLayerExtension when no proxy env vars are set', () => {
140+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
141+
const options: AwsServerlessOptions = {};
142+
143+
init(options);
144+
145+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
146+
expect.objectContaining({
147+
useLayerExtension: true,
148+
tunnel: 'http://localhost:9000/envelope',
149+
}),
150+
);
151+
});
152+
153+
test('should disable useLayerExtension when http_proxy is set', () => {
154+
process.env.http_proxy = 'http://proxy.example.com:8080';
155+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
156+
const options: AwsServerlessOptions = {};
157+
158+
init(options);
159+
160+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
161+
expect.objectContaining({
162+
useLayerExtension: false,
163+
}),
164+
);
165+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
166+
expect.not.objectContaining({
167+
tunnel: expect.any(String),
168+
}),
169+
);
170+
});
171+
172+
describe('no_proxy patterns', () => {
173+
test('should enable useLayerExtension when no_proxy=* (wildcard)', () => {
174+
process.env.http_proxy = 'http://proxy.example.com:8080';
175+
process.env.no_proxy = '*';
176+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
177+
const options: AwsServerlessOptions = {};
178+
179+
init(options);
180+
181+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
182+
expect.objectContaining({
183+
useLayerExtension: true,
184+
tunnel: 'http://localhost:9000/envelope',
185+
}),
186+
);
187+
});
188+
189+
test('should enable useLayerExtension when no_proxy contains localhost', () => {
190+
process.env.http_proxy = 'http://proxy.example.com:8080';
191+
process.env.no_proxy = 'localhost';
192+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
193+
const options: AwsServerlessOptions = {};
194+
195+
init(options);
196+
197+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
198+
expect.objectContaining({
199+
useLayerExtension: true,
200+
tunnel: 'http://localhost:9000/envelope',
201+
}),
202+
);
203+
});
204+
205+
test('should enable useLayerExtension when no_proxy contains 127.0.0.1', () => {
206+
process.env.http_proxy = 'http://proxy.example.com:8080';
207+
process.env.no_proxy = '127.0.0.1';
208+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
209+
const options: AwsServerlessOptions = {};
210+
211+
init(options);
212+
213+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
214+
expect.objectContaining({
215+
useLayerExtension: true,
216+
tunnel: 'http://localhost:9000/envelope',
217+
}),
218+
);
219+
});
220+
221+
test('should enable useLayerExtension when no_proxy contains ::1', () => {
222+
process.env.http_proxy = 'http://proxy.example.com:8080';
223+
process.env.no_proxy = '::1';
224+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
225+
const options: AwsServerlessOptions = {};
226+
227+
init(options);
228+
229+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
230+
expect.objectContaining({
231+
useLayerExtension: true,
232+
tunnel: 'http://localhost:9000/envelope',
233+
}),
234+
);
235+
});
236+
237+
test('should enable useLayerExtension when no_proxy contains localhost in a comma-separated list', () => {
238+
process.env.http_proxy = 'http://proxy.example.com:8080';
239+
process.env.no_proxy = 'example.com,localhost,other.com';
240+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
241+
const options: AwsServerlessOptions = {};
242+
243+
init(options);
244+
245+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
246+
expect.objectContaining({
247+
useLayerExtension: true,
248+
tunnel: 'http://localhost:9000/envelope',
249+
}),
250+
);
251+
});
252+
253+
test('should disable useLayerExtension when no_proxy does not contain localhost patterns', () => {
254+
process.env.http_proxy = 'http://proxy.example.com:8080';
255+
process.env.no_proxy = 'example.com,other.com';
256+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
257+
const options: AwsServerlessOptions = {};
258+
259+
init(options);
260+
261+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
262+
expect.objectContaining({
263+
useLayerExtension: false,
264+
}),
265+
);
266+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
267+
expect.not.objectContaining({
268+
tunnel: expect.any(String),
269+
}),
270+
);
271+
});
272+
273+
test('should disable useLayerExtension when no_proxy contains host (no longer supported)', () => {
274+
process.env.http_proxy = 'http://proxy.example.com:8080';
275+
process.env.no_proxy = 'host';
276+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
277+
const options: AwsServerlessOptions = {};
278+
279+
init(options);
280+
281+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
282+
expect.objectContaining({
283+
useLayerExtension: false,
284+
}),
285+
);
286+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
287+
expect.not.objectContaining({
288+
tunnel: expect.any(String),
289+
}),
290+
);
291+
});
292+
293+
test('should handle case-insensitive no_proxy values', () => {
294+
process.env.http_proxy = 'http://proxy.example.com:8080';
295+
process.env.no_proxy = 'LOCALHOST';
296+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
297+
const options: AwsServerlessOptions = {};
298+
299+
init(options);
300+
301+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
302+
expect.objectContaining({
303+
useLayerExtension: true,
304+
tunnel: 'http://localhost:9000/envelope',
305+
}),
306+
);
307+
});
308+
309+
test('should handle whitespace in no_proxy values', () => {
310+
process.env.http_proxy = 'http://proxy.example.com:8080';
311+
process.env.no_proxy = ' localhost , example.com ';
312+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
313+
const options: AwsServerlessOptions = {};
314+
315+
init(options);
316+
317+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
318+
expect.objectContaining({
319+
useLayerExtension: true,
320+
tunnel: 'http://localhost:9000/envelope',
321+
}),
322+
);
323+
});
324+
});
325+
326+
test('should respect explicit useLayerExtension=false even with no proxy interference', () => {
327+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
328+
const options: AwsServerlessOptions = {
329+
useLayerExtension: false,
330+
};
331+
332+
init(options);
333+
334+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
335+
expect.objectContaining({
336+
useLayerExtension: false,
337+
}),
338+
);
339+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
340+
expect.not.objectContaining({
341+
tunnel: expect.any(String),
342+
}),
343+
);
344+
});
345+
346+
test('should respect explicit useLayerExtension=false even with proxy that would interfere', () => {
347+
process.env.http_proxy = 'http://proxy.example.com:8080';
348+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
349+
const options: AwsServerlessOptions = {
350+
useLayerExtension: false,
351+
};
352+
353+
init(options);
354+
355+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
356+
expect.objectContaining({
357+
useLayerExtension: false,
358+
}),
359+
);
360+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
361+
expect.not.objectContaining({
362+
tunnel: expect.any(String),
363+
}),
364+
);
365+
});
366+
367+
test('should respect explicit useLayerExtension=false even when no_proxy would enable it', () => {
368+
process.env.http_proxy = 'http://proxy.example.com:8080';
369+
process.env.no_proxy = 'localhost';
370+
mockGetSDKSource.mockReturnValue('aws-lambda-layer');
371+
const options: AwsServerlessOptions = {
372+
useLayerExtension: false,
373+
};
374+
375+
init(options);
376+
377+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
378+
expect.objectContaining({
379+
useLayerExtension: false,
380+
}),
381+
);
382+
expect(mockInitWithoutDefaultIntegrations).toHaveBeenCalledWith(
383+
expect.not.objectContaining({
384+
tunnel: expect.any(String),
385+
}),
386+
);
387+
});
388+
});
131389
});

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /