diff --git a/.castiron.stats.yml b/.castiron.stats.yml index c94901d94..46c947cec 100644 --- a/.castiron.stats.yml +++ b/.castiron.stats.yml @@ -1,8 +1,8 @@ schema_version: 1 -generation_id: fae2b2d8-b06e-4a75-b296-019934b8950a +generation_id: b1cc4193-4b37-4231-bc0a-c97dcbe985f7 openapi_spec_hash: 4af7018ff56446e0398fc7946a92680f openapi_transformed_spec_hash: b2689771e08c3fdc6ae8f0433dc2c784 config_hash: 5c00fe18ea913ed0186f9894adc02a70 -codegen_sha: 05bcb472a761f436c08e48a9824417549667ae4b -codegen_hash: 042057870974b799dd5a454a004f5b934f9a0d33ac185c02c3946f19abd72fc4 -public_codegen_sha: ff25c619e1f38e199d8a909019e01cf4be37adb5 +codegen_sha: 4d3155b4c645e90b0a2d754982db6245de8b372d +codegen_hash: a6e4616dbb72afa61505b2333668b0f6787e9640cb63a06a09776b943c10e731 +public_codegen_sha: 65094c1637432c123c310d03e0cda1e7e6f1c997 diff --git a/scripts/test-packed-package.ts b/scripts/test-packed-package.ts index 027a9064b..c181955d2 100644 --- a/scripts/test-packed-package.ts +++ b/scripts/test-packed-package.ts @@ -163,6 +163,7 @@ const packedPackagePath = require('node:path'); [ "declare module 'ws' {", ' export interface ClientOptions {', + ' followRedirects?: boolean | undefined;', ' headers?: Record | undefined;', ' }', ' export class WebSocket {', diff --git a/src/resources/beta/responses/ws.ts b/src/resources/beta/responses/ws.ts index cda20f47b..de34a75ad 100644 --- a/src/resources/beta/responses/ws.ts +++ b/src/resources/beta/responses/ws.ts @@ -35,6 +35,7 @@ export class ResponsesWS extends ResponsesWSBase { ...authHeaders, ...this._wsOptions?.headers, }, + followRedirects: false, }); return new NodeWebSocket(ws); } diff --git a/src/resources/responses/ws.ts b/src/resources/responses/ws.ts index 96787765a..74361cfe5 100644 --- a/src/resources/responses/ws.ts +++ b/src/resources/responses/ws.ts @@ -35,6 +35,7 @@ export class ResponsesWS extends ResponsesWSBase { ...authHeaders, ...this._wsOptions?.headers, }, + followRedirects: false, }); return new NodeWebSocket(ws); } diff --git a/tests/bedrock-websocket-security.test.ts b/tests/bedrock-websocket-security.test.ts index 71a2062f5..7d2276f35 100644 --- a/tests/bedrock-websocket-security.test.ts +++ b/tests/bedrock-websocket-security.test.ts @@ -408,7 +408,7 @@ describe.each([ { name: 'stable', Responses: StableResponsesWS }, { name: 'beta', Responses: BetaResponsesWS }, ])('$name Responses WebSocket redirect options', ({ Responses }) => { - test('preserves explicitly enabled redirects without sensitive headers', () => { + test('disables explicitly enabled redirects without sensitive headers', () => { const websocket = new Responses(createUnauthenticatedClient(), { followRedirects: true, headers: { 'X-Custom': 'value' }, @@ -416,7 +416,7 @@ describe.each([ expect(websocket.socket.platformSocket).toBe(lastNodeSocket()); expect(lastNodeSocket().options).toMatchObject({ - followRedirects: true, + followRedirects: false, headers: { 'X-Custom': 'value' }, }); expect(lastNodeSocket().options.headers).not.toHaveProperty('Authorization'); diff --git a/tests/realtime-websocket-custom-credential-redirects.test.ts b/tests/realtime-websocket-custom-credential-redirects.test.ts index 11b056209..dfb2250e9 100644 --- a/tests/realtime-websocket-custom-credential-redirects.test.ts +++ b/tests/realtime-websocket-custom-credential-redirects.test.ts @@ -255,11 +255,11 @@ describe.each([ expect(result.sourceCredentials).toEqual([value]); expect(result.destinationCredentials).toEqual([]); - expect(result.redirects).toBe(1); - expect(result.error.message).toBe('WebSocket was closed before the connection was established'); + expect(result.redirects).toBe(0); + expect(result.error.message).toBe('Unexpected server response: 302'); expect(result.publicErrors).toEqual([ expect.objectContaining({ - message: 'WebSocket was closed before the connection was established', + message: 'Unexpected server response: 302', }), ]); }, @@ -278,7 +278,11 @@ describe.each([ expect(result.sourceCredentials).toEqual([value]); expect(result.destinationCredentials).toEqual([]); - expect(result.redirects).toBe(1); + expect(result.redirects).toBe(0); + expect(result.error.message).toBe(`Unexpected server response: ${status}`); + expect(result.publicErrors).toEqual([ + expect.objectContaining({ message: `Unexpected server response: ${status}` }), + ]); }, ); @@ -293,10 +297,14 @@ describe.each([ expect(result.sourceCredentials).toEqual([value]); expect(result.destinationCredentials).toEqual([]); - expect(result.redirects).toBe(1); + expect(result.redirects).toBe(0); + expect(result.error.message).toBe('Unexpected server response: 302'); + expect(result.publicErrors).toEqual([ + expect.objectContaining({ message: 'Unexpected server response: 302' }), + ]); }); - test.each([false, true])('preserves benign %s-origin redirect behavior', async (sameOrigin) => { + test.each([false, true])('disables benign %s-origin redirects', async (sameOrigin) => { const value = 'ordinary-nonsensitive-header-value'; const result = await inspectRedirect({ Responses, @@ -306,8 +314,11 @@ describe.each([ }); expect(result.sourceCredentials).toEqual([value]); - expect(result.destinationCredentials).toEqual([value]); - expect(result.redirects).toBe(1); - expect(result.error.message).toBe('Unexpected server response: 200'); + expect(result.destinationCredentials).toEqual([]); + expect(result.redirects).toBe(0); + expect(result.error.message).toBe('Unexpected server response: 302'); + expect(result.publicErrors).toEqual([ + expect.objectContaining({ message: 'Unexpected server response: 302' }), + ]); }); }); diff --git a/tests/realtime-websocket-redirects.test.ts b/tests/realtime-websocket-redirects.test.ts index 6a0cd62dd..9125e38d4 100644 --- a/tests/realtime-websocket-redirects.test.ts +++ b/tests/realtime-websocket-redirects.test.ts @@ -482,9 +482,9 @@ describe.each([ expect(sourceCredentials).toEqual([value]); expect(destinationRequests).toEqual([]); - expect(redirects).toHaveBeenCalledTimes(1); + expect(redirects).not.toHaveBeenCalled(); expect(errors).toHaveBeenCalledWith( - expect.objectContaining({ message: 'WebSocket was closed before the connection was established' }), + expect.objectContaining({ message: 'Unexpected server response: 302' }), ); } finally { await closeServers(source, destination);