From 28743d910b877bc81e2a48b5da44165d65b31073 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Mon, 23 Jun 2025 17:03:13 +0200 Subject: [PATCH 1/3] fix(astro): Try-catch `controller.close()` usage --- packages/astro/src/server/middleware.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/astro/src/server/middleware.ts b/packages/astro/src/server/middleware.ts index f339f7b6f979..bb92e6764fa6 100644 --- a/packages/astro/src/server/middleware.ts +++ b/packages/astro/src/server/middleware.ts @@ -194,7 +194,12 @@ async function instrumentRequest( sendErrorToSentry(e); controller.error(e); } finally { - controller.close(); + // try catch this, as it could have been manually closed by a user-land middleware + try { + controller.close(); + } catch { + // we assume this means it was already closed + } } }, }); From 82c0250b2051edc8bd5b935f9eb8697e1ef6cca0 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Wed, 25 Jun 2025 13:25:42 +0200 Subject: [PATCH 2/3] better handling of errors --- packages/astro/src/server/middleware.ts | 27 +++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/packages/astro/src/server/middleware.ts b/packages/astro/src/server/middleware.ts index bb92e6764fa6..11fca078a619 100644 --- a/packages/astro/src/server/middleware.ts +++ b/packages/astro/src/server/middleware.ts @@ -184,22 +184,33 @@ async function instrumentRequest( const newResponseStream = new ReadableStream({ start: async controller => { + // Assign to a new variable to avoid TS losing the narrower type checked above. + const body = originalBody; + + async function* bodyReporter(): AsyncGenerator { + try { + for await (const chunk of body) { + yield chunk; + } + } catch (e) { + // Report stream errors coming from user code or Astro rendering. + sendErrorToSentry(e); + throw e; + } + } + + const reportedBody = bodyReporter(); + try { - for await (const chunk of originalBody) { + for await (const chunk of reportedBody) { const html = typeof chunk === 'string' ? chunk : decoder.decode(chunk, { stream: true }); const modifiedHtml = addMetaTagToHead(html); controller.enqueue(new TextEncoder().encode(modifiedHtml)); } } catch (e) { - sendErrorToSentry(e); controller.error(e); } finally { - // try catch this, as it could have been manually closed by a user-land middleware - try { - controller.close(); - } catch { - // we assume this means it was already closed - } + controller.close(); } }, }); From bd0f08c3182047e360e79a60e37e87089c1e2e33 Mon Sep 17 00:00:00 2001 From: Francesco Novy Date: Fri, 27 Jun 2025 10:42:19 +0200 Subject: [PATCH 3/3] avoid const --- packages/astro/src/server/middleware.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/packages/astro/src/server/middleware.ts b/packages/astro/src/server/middleware.ts index 11fca078a619..5aabfa8d7351 100644 --- a/packages/astro/src/server/middleware.ts +++ b/packages/astro/src/server/middleware.ts @@ -199,10 +199,8 @@ async function instrumentRequest( } } - const reportedBody = bodyReporter(); - try { - for await (const chunk of reportedBody) { + for await (const chunk of bodyReporter()) { const html = typeof chunk === 'string' ? chunk : decoder.decode(chunk, { stream: true }); const modifiedHtml = addMetaTagToHead(html); controller.enqueue(new TextEncoder().encode(modifiedHtml));