Skip to content

fix(cloudflare/workers): drain pre-response handlers in serveWebRequest#178

Open
Mkassabov wants to merge 3 commits into
mainfrom
fix/cloudflare-worker-pre-response-handlers
Open

fix(cloudflare/workers): drain pre-response handlers in serveWebRequest#178
Mkassabov wants to merge 3 commits into
mainfrom
fix/cloudflare-worker-pre-response-handlers

Conversation

@Mkassabov
Copy link
Copy Markdown
Contributor

HttpMiddleware.cors() (and any other middleware that registers a preResponseHandler for non-OPTIONS requests) was a no-op on real responses inside a Cloudflare.Worker — only OPTIONS preflights short-circuited with CORS headers. serveWebRequest ran the handler and converted the result straight to a web Response, never draining the pre-response queue.

Run the handler through effect's public HttpEffect.toHandled so the registered pre-response handler chain fires before the response is converted. scopeTransferToStream keeps streaming bodies' scopes closing on stream end.

-    const response = yield* handler.pipe(
-      Effect.provideService(HttpServerRequest.HttpServerRequest, request),
-      Effect.provideService(Request, webRequest as any),
-      Effect.catchCause(...),
-    );
-    return HttpServerResponse.toWeb(response, { context: yield* Effect.context() });
+    const httpApp = HttpEffectModule.toHandled(handler, (_req, response) => {
+      const transferred = HttpEffectModule.scopeTransferToStream(response);
+      resume(Effect.succeed(HttpServerResponse.toWeb(transferred, { context: parentContext })));
+      return Effect.void;
+    });
+    httpApp.pipe(
+      Effect.provideService(HttpServerRequest.HttpServerRequest, request),
+      Effect.provideService(Request, webRequest as any),
+      Effect.provide(parentContext),
+      Effect.runFork,
+    );

Verified against the repro from #175: both OPTIONS preflight and GET now carry Access-Control-Allow-Origin.

Fixes #175

`HttpMiddleware.cors()` (and any other middleware that registers a
`preResponseHandler` for non-OPTIONS requests) was a no-op on real
responses inside a `Cloudflare.Worker` — only OPTIONS preflights
short-circuited with CORS headers. Run the handler through
`HttpEffect.toHandled` so the registered pre-response handler chain
fires before the response is converted to a web `Response`.

Fixes #175
@alchemy-version-bot
Copy link
Copy Markdown
Contributor

alchemy-version-bot Bot commented May 4, 2026

Install the packages built from this commit:

alchemy

bun add alchemy@https://pkg.ing/alchemy/245e617

@alchemy.run/better-auth

bun add @alchemy.run/better-auth@https://pkg.ing/@alchemy.run/better-auth/245e617

@alchemy.run/pr-package

bun add @alchemy.run/pr-package@https://pkg.ing/@alchemy.run/pr-package/245e617

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

HttpMiddleware.cors() doesn't tag non-preflight responses when used inside a Cloudflare.Worker

1 participant