Skip to content

feat(cloudflare): always augment request with cf context#3904

Merged
pi0 merged 9 commits into
nitrojs:mainfrom
emretinaztepe:fix/cloudflare-ws-context
Jan 9, 2026
Merged

feat(cloudflare): always augment request with cf context#3904
pi0 merged 9 commits into
nitrojs:mainfrom
emretinaztepe:fix/cloudflare-ws-context

Conversation

@emretinaztepe
Copy link
Copy Markdown
Contributor

Currently, there is no way to access or pass Cloudflare env and bindings for websockets.

This PR passes the Cloudflare environment and context to the CrossWS peer, making bindings accessible within WS handlers.

@emretinaztepe emretinaztepe requested a review from pi0 as a code owner December 30, 2025 00:40
@vercel
Copy link
Copy Markdown

vercel Bot commented Dec 30, 2025

@emretinaztepe is attempting to deploy a commit to the Nitro Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Dec 30, 2025

Warning

Rate limit exceeded

@pi0 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 34 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between 72d9d85 and 772948a.

📒 Files selected for processing (3)
  • src/presets/cloudflare/runtime/_module-handler.ts
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
  • src/presets/cloudflare/runtime/cloudflare-pages.ts
📝 Walkthrough

Walkthrough

Extracts per-request Cloudflare context augmentation into a new augmentReq helper, removes the local fetchHandler, and updates Cloudflare Module, Pages, and Durable runtimes to call augmentReq and to route main requests via nitroApp.fetch; WebSocket and asset handling adjusted to use the augmented request. Public APIs unchanged.

Changes

Cohort / File(s) Summary
Core augmentation helper
src/presets/cloudflare/runtime/_module-handler.ts
Adds exported `augmentReq(cfReq: Request
Durable runtime
src/presets/cloudflare/runtime/cloudflare-durable.ts
Imports and invokes augmentReq at request start (including inside DurableObject fetch), casts requests passed to env.ASSETS.fetch and ctxExt.durableFetch as any, and delegates WebSocket upgrades to ws!.handleDurableUpgrade when applicable; main path now returns nitroApp.fetch(request).
Module runtime
src/presets/cloudflare/runtime/cloudflare-module.ts
Renames fetch parameter to cfRequest, uses cfRequest for static asset proxy (env.ASSETS.fetch) and WebSocket upgrade checks/handlers, and routes main fetch via nitroApp.fetch(cfRequest as any).
Pages runtime
src/presets/cloudflare/runtime/cloudflare-pages.ts
Replaces manual cfReq.runtime and waitUntil assignments with augmentReq(cfReq, env, context), stops exposing env on globalThis, passes cfReq to websocket upgrade handler, and calls nitroApp.fetch(cfReq as any) for main fetch.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The PR title follows conventional commits format with 'feat' type and clear scope, accurately describing the main change of augmenting requests with Cloudflare context.
Description check ✅ Passed The PR description clearly explains the problem (no access to Cloudflare env/bindings for WebSockets) and the solution (augmenting request with context), directly relating to the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/presets/cloudflare/runtime/cloudflare-durable.ts (1)

55-64: Logic looks correct for passing Cloudflare bindings to WebSocket handlers.

The implementation properly initializes request.context with Cloudflare bindings before delegating to the WebSocket upgrade handler. The use of Object.defineProperty with enumerable: true and the ||= operators ensure safe initialization.

However, this exact logic is duplicated in src/presets/cloudflare/runtime/cloudflare-module.ts (lines 28-37). Consider extracting this initialization into a shared helper function in _module-handler.ts to reduce duplication:

// In _module-handler.ts
function initializeWebSocketContext(
  request: Request,
  env: any,
  context: any
): void {
  let wsContext = (request as any).context;
  if (!wsContext) {
    wsContext = {};
    Object.defineProperty(request as any, "context", { 
      enumerable: true, 
      value: wsContext 
    });
  }
  wsContext.cloudflare ||= {};
  wsContext.cloudflare.env ||= env;
  wsContext.cloudflare.context ||= context;
}

Then use in both files:

initializeWebSocketContext(request, env, context);
return ws!.handleUpgrade(request, env, context);

Note: The comment stating "crossws will forward request.context to peer.context" may be inaccurate. According to crossws documentation, context should be forwarded via ctx.props (ExecutionContext properties) rather than request.context. Verify if the current approach actually works as intended or if context.props should be used instead.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1a1198e and a1fd9d9.

📒 Files selected for processing (2)
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
  • src/presets/cloudflare/runtime/cloudflare-module.ts
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{ts,js,tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,js,tsx,jsx}: Use pathe for cross-platform path operations instead of Node.js node:path
Use ESM and modern JavaScript
Do not add comments explaining what the line does unless prompted

Files:

  • src/presets/cloudflare/runtime/cloudflare-module.ts
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
src/**/*.{ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

Use unstorage for storage abstraction

Files:

  • src/presets/cloudflare/runtime/cloudflare-module.ts
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
🧠 Learnings (3)
📚 Learning: 2025-12-24T11:45:17.416Z
Learnt from: CR
Repo: nitrojs/nitro PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-24T11:45:17.416Z
Learning: Applies to src/runtime/**/*.{ts,js} : In runtime code, prefer Web APIs (fetch, Request, Response, URL, etc.) over Node.js APIs

Applied to files:

  • src/presets/cloudflare/runtime/cloudflare-module.ts
📚 Learning: 2025-12-03T19:09:13.905Z
Learnt from: medz
Repo: nitrojs/nitro PR: 3834
File: src/presets/cloudflare/server-entry.ts:63-63
Timestamp: 2025-12-03T19:09:13.905Z
Learning: In the Nitro Cloudflare preset (src/presets/cloudflare/server-entry.ts), native errors from oxc-parser and Node.js readFile operations should be allowed to bubble up naturally without wrapping, as their native error messages are more user-friendly and provide better diagnostic information.

Applied to files:

  • src/presets/cloudflare/runtime/cloudflare-module.ts
📚 Learning: 2025-12-24T11:45:17.416Z
Learnt from: CR
Repo: nitrojs/nitro PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-24T11:45:17.416Z
Learning: Applies to src/runtime/**/*.{ts,js} : Keep runtime code minimal and side-effect free to reduce bundle size

Applied to files:

  • src/presets/cloudflare/runtime/cloudflare-module.ts
🧬 Code graph analysis (2)
src/presets/cloudflare/runtime/cloudflare-module.ts (1)
src/runtime/internal/vite/node-runner.mjs (1)
  • env (174-174)
src/presets/cloudflare/runtime/cloudflare-durable.ts (1)
src/runtime/internal/vite/node-runner.mjs (1)
  • env (174-174)
🔇 Additional comments (1)
src/presets/cloudflare/runtime/cloudflare-module.ts (1)

28-37: LGTM! Implementation correctly initializes Cloudflare bindings for WebSocket context.

The logic mirrors the implementation in cloudflare-durable.ts and correctly ensures env and context are accessible within WebSocket handlers via peer.context.

Note: The code duplication concern and refactoring suggestion were already mentioned in the review of cloudflare-durable.ts (lines 55-64).

@pi0 pi0 changed the title fix: pass cloudflare env & context in websocket context fix(cloudflare-durable): pass cloudflare env & context in websocket context Jan 8, 2026
@pi0 pi0 changed the title fix(cloudflare-durable): pass cloudflare env & context in websocket context feat(cloudflare-module, cloudflare-durable): pass cloudflare env and context in websocket context Jan 8, 2026
@pi0
Copy link
Copy Markdown
Member

pi0 commented Jan 8, 2026

Thanks. This looks like a nice enhancenment, however, it seems we can always inject env and context in shared fetch handler to request object so it works both in ws upgrades and nornmal paths (we seem missing it in v3)

@emretinaztepe
Copy link
Copy Markdown
Contributor Author

@pi0 Any plans to add it to the shared fetch handler soon? I am currently using a local pnpm patch to work around it and would love to remove it as soon as it is officially supported.

@pi0
Copy link
Copy Markdown
Member

pi0 commented Jan 8, 2026

I think you can refactor your PR to do this so we can merge/release it asap!

@emretinaztepe
Copy link
Copy Markdown
Contributor Author

@pi0 I believe it should be fixed for all handlers to be available for all Cloudflare Worker entrypoints such as email, scheduled, etc. What do you think?

@pi0
Copy link
Copy Markdown
Member

pi0 commented Jan 8, 2026

We could make an internal util like augmentContext(req, env, ctx) perhaps and call it in all?

@pkg-pr-new
Copy link
Copy Markdown

pkg-pr-new Bot commented Jan 8, 2026

Open in StackBlitz

npm i https://pkg.pr.new/nitrojs/nitro@3904

commit: 0f3859b

@emretinaztepe
Copy link
Copy Markdown
Contributor Author

@pi0 That makes sense, but I am afraid I am not familiar with the implementation of other presets. I will push a refactored version. Please feel free to modify it if it doesn't make sense.

@emretinaztepe emretinaztepe requested a review from pi0 January 9, 2026 00:19
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In @src/presets/cloudflare/runtime/_module-handler.ts:
- Around line 10-14: The function signature for augmentContext uses an
un-prefixed DurableObjectState which will fail TS compile; update the parameter
type to use the Cloudflare namespace by changing DurableObjectState to
CF.DurableObjectState in the augmentContext declaration so it matches the other
CF.* types (i.e., ensure the third param is typed as CF.ExecutionContext |
CF.DurableObjectState).
- Around line 61-62: There is a redundant augmentContext(request, env, context)
call before invoking hooks.fetch; remove that duplicate call (the one outside
fetchHandler) or make it conditional so augmentation only happens once: keep
augmentContext inside fetchHandler (since fetchHandler is also called directly
from cloudflare-durable.ts) and either delete the pre-fetchHandler call at line
61 or add a guard on context (e.g., context.__augmented) so hooks.fetch can rely
on an augmented context without causing double augmentation.
🧹 Nitpick comments (2)
src/presets/cloudflare/runtime/_module-handler.ts (1)

81-149: Consider consolidating env exposure for non-fetch handlers.

The scheduled, email, queue, tail, and trace handlers all repeat (globalThis as any).__env__ = env; inline. Per the PR discussion, the goal was to call a shared utility from all entrypoints.

Since these handlers lack a request object, you could extract a minimal helper (e.g., exposeEnv(env)) or extend augmentContext to accept an optional request. This would reduce duplication and centralize the global env exposure pattern.

src/presets/cloudflare/runtime/cloudflare-pages.ts (1)

63-77: Consider using a shared env exposure helper for consistency.

The scheduled handler still has inline (globalThis as any).__env__ = env; (line 65), mirroring the pattern in _module-handler.ts. If you extract a shared helper for env exposure as suggested for the other handlers, this could be consolidated as well.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8211f4a and f0cef81.

📒 Files selected for processing (3)
  • src/presets/cloudflare/runtime/_module-handler.ts
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
  • src/presets/cloudflare/runtime/cloudflare-pages.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{ts,js,tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,js,tsx,jsx}: Use pathe for cross-platform path operations instead of Node.js node:path
Use ESM and modern JavaScript
Do not add comments explaining what the line does unless prompted

Files:

  • src/presets/cloudflare/runtime/_module-handler.ts
  • src/presets/cloudflare/runtime/cloudflare-pages.ts
src/**/*.{ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

Use unstorage for storage abstraction

Files:

  • src/presets/cloudflare/runtime/_module-handler.ts
  • src/presets/cloudflare/runtime/cloudflare-pages.ts
🧠 Learnings (3)
📚 Learning: 2025-12-24T11:45:17.435Z
Learnt from: CR
Repo: nitrojs/nitro PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-24T11:45:17.435Z
Learning: Applies to src/runtime/**/*.{ts,js} : In runtime code, prefer Web APIs (fetch, Request, Response, URL, etc.) over Node.js APIs

Applied to files:

  • src/presets/cloudflare/runtime/_module-handler.ts
  • src/presets/cloudflare/runtime/cloudflare-pages.ts
📚 Learning: 2025-12-24T11:45:17.435Z
Learnt from: CR
Repo: nitrojs/nitro PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-24T11:45:17.435Z
Learning: Applies to src/runtime/**/*.{ts,js} : Keep runtime code minimal and side-effect free to reduce bundle size

Applied to files:

  • src/presets/cloudflare/runtime/_module-handler.ts
  • src/presets/cloudflare/runtime/cloudflare-pages.ts
📚 Learning: 2025-12-03T19:09:13.905Z
Learnt from: medz
Repo: nitrojs/nitro PR: 3834
File: src/presets/cloudflare/server-entry.ts:63-63
Timestamp: 2025-12-03T19:09:13.905Z
Learning: In the Nitro Cloudflare preset (src/presets/cloudflare/server-entry.ts), native errors from oxc-parser and Node.js readFile operations should be allowed to bubble up naturally without wrapping, as their native error messages are more user-friendly and provide better diagnostic information.

Applied to files:

  • src/presets/cloudflare/runtime/_module-handler.ts
  • src/presets/cloudflare/runtime/cloudflare-pages.ts
🧬 Code graph analysis (2)
src/presets/cloudflare/runtime/_module-handler.ts (1)
src/types/srvx.ts (1)
  • ServerRequest (1-1)
src/presets/cloudflare/runtime/cloudflare-pages.ts (1)
src/presets/cloudflare/runtime/_module-handler.ts (1)
  • augmentContext (10-42)
🔇 Additional comments (2)
src/presets/cloudflare/runtime/_module-handler.ts (1)

15-41: LGTM!

The augmentation logic correctly handles both srvx and crossws compatibility. The use of spread operators preserves existing values, and Object.defineProperty appropriately creates the context object when needed.

src/presets/cloudflare/runtime/cloudflare-pages.ts (1)

42-44: LGTM!

The refactoring correctly delegates context augmentation to the shared helper. The as any cast on context is acceptable given the type difference between EventContext and ExecutionContext.

Comment thread src/presets/cloudflare/runtime/_module-handler.ts Outdated
Comment thread src/presets/cloudflare/runtime/_module-handler.ts Outdated
@pi0 pi0 changed the title feat(cloudflare-module, cloudflare-durable): pass cloudflare env and context in websocket context feat: always augment request with cf context Jan 9, 2026
Comment thread src/presets/cloudflare/runtime/_module-handler.ts Outdated
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/presets/cloudflare/runtime/_module-handler.ts (1)

13-13: Fix type reference: use CF.ExportedHandler.

Both lines reference ExportedHandler<Env> without the CF. namespace prefix, which will cause TypeScript compilation errors. Since the import at line 2 uses import type * as CF from "@cloudflare/workers-types", the type should be CF.ExportedHandler<Env>.

🔧 Proposed fix
 export function createHandler<Env>(hooks: {
   fetch: (
     ...params: [
-      ...Parameters<NonNullable<ExportedHandler<Env>["fetch"]>>,
+      ...Parameters<NonNullable<CF.ExportedHandler<Env>["fetch"]>>,
       url: URL,
       cfContextExtras: any,
     ]
   ) => MaybePromise<Response | CF.Response | undefined>;
 }) {
       context,
     });
   },
- } satisfies ExportedHandler<Env>;
+ } satisfies CF.ExportedHandler<Env>;
 }

Also applies to: 110-110

🤖 Fix all issues with AI agents
In @src/presets/cloudflare/runtime/_module-handler.ts:
- Around line 113-126: The function augmentReq currently types the context
parameter as DurableObjectState without the CF namespace; update the signature
of augmentReq to use CF.DurableObjectState for the context parameter and any
other references to DurableObjectState in this function so it consistently
refers to the imported type namespace (e.g., change "context:
CF.ExecutionContext | DurableObjectState" to "context: CF.ExecutionContext |
CF.DurableObjectState" in the augmentReq declaration).
🧹 Nitpick comments (3)
src/presets/cloudflare/runtime/cloudflare-module.ts (1)

19-23: Parameter rename improves clarity.

The rename from request to cfRequest effectively signals that this is the Cloudflare-specific request parameter. The static assets delegation is correct.

However, the as any cast on line 22 reduces type safety. If the type mismatch is due to differences between the standard Request type and Cloudflare's extended request type, consider whether a more specific type assertion would be safer.

src/presets/cloudflare/runtime/cloudflare-durable.ts (1)

46-46: Consider more specific type assertions.

The as any casts reduce type safety. If these are necessary due to type mismatches between standard Request and Cloudflare's extended types, consider whether more specific type assertions would be safer and more maintainable.

Also applies to: 50-51

src/presets/cloudflare/runtime/_module-handler.ts (1)

24-25: LGTM! Request augmentation correctly positioned.

The augmentation at line 25 happens early in the fetch flow, ensuring all downstream handlers (including WebSocket upgrades and preset-specific logic) have access to the Cloudflare env and context. The simplified return at line 38 is cleaner.

The as any casts reduce type safety but may be necessary due to type system limitations between Web API types and Cloudflare-specific types.

Also applies to: 38-38

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between f0cef81 and 909ae65.

📒 Files selected for processing (4)
  • src/presets/cloudflare/runtime/_module-handler.ts
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
  • src/presets/cloudflare/runtime/cloudflare-module.ts
  • src/presets/cloudflare/runtime/cloudflare-pages.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/presets/cloudflare/runtime/cloudflare-pages.ts
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{ts,js,tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,js,tsx,jsx}: Use pathe for cross-platform path operations instead of Node.js node:path
Use ESM and modern JavaScript
Do not add comments explaining what the line does unless prompted

Files:

  • src/presets/cloudflare/runtime/cloudflare-module.ts
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
  • src/presets/cloudflare/runtime/_module-handler.ts
src/**/*.{ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

Use unstorage for storage abstraction

Files:

  • src/presets/cloudflare/runtime/cloudflare-module.ts
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
  • src/presets/cloudflare/runtime/_module-handler.ts
🧠 Learnings (3)
📚 Learning: 2025-12-24T11:45:17.435Z
Learnt from: CR
Repo: nitrojs/nitro PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-24T11:45:17.435Z
Learning: Applies to src/runtime/**/*.{ts,js} : In runtime code, prefer Web APIs (fetch, Request, Response, URL, etc.) over Node.js APIs

Applied to files:

  • src/presets/cloudflare/runtime/cloudflare-module.ts
  • src/presets/cloudflare/runtime/cloudflare-durable.ts
  • src/presets/cloudflare/runtime/_module-handler.ts
📚 Learning: 2025-12-03T19:09:13.905Z
Learnt from: medz
Repo: nitrojs/nitro PR: 3834
File: src/presets/cloudflare/server-entry.ts:63-63
Timestamp: 2025-12-03T19:09:13.905Z
Learning: In the Nitro Cloudflare preset (src/presets/cloudflare/server-entry.ts), native errors from oxc-parser and Node.js readFile operations should be allowed to bubble up naturally without wrapping, as their native error messages are more user-friendly and provide better diagnostic information.

Applied to files:

  • src/presets/cloudflare/runtime/cloudflare-durable.ts
  • src/presets/cloudflare/runtime/_module-handler.ts
📚 Learning: 2025-12-24T11:45:17.435Z
Learnt from: CR
Repo: nitrojs/nitro PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-24T11:45:17.435Z
Learning: Applies to src/runtime/**/*.{ts,js} : Keep runtime code minimal and side-effect free to reduce bundle size

Applied to files:

  • src/presets/cloudflare/runtime/_module-handler.ts
🧬 Code graph analysis (3)
src/presets/cloudflare/runtime/cloudflare-module.ts (4)
src/runtime/internal/vite/node-runner.mjs (1)
  • url (309-309)
src/runtime/virtual/public-assets.ts (1)
  • isPublicAssetURL (6-6)
src/runtime/virtual/feature-flags.ts (1)
  • hasWebSocket (9-9)
src/runtime/internal/vite/dev-entry.mjs (1)
  • ws (12-14)
src/presets/cloudflare/runtime/cloudflare-durable.ts (3)
src/presets/cloudflare/runtime/_module-handler.ts (1)
  • augmentReq (113-126)
src/runtime/virtual/feature-flags.ts (1)
  • hasWebSocket (9-9)
src/runtime/internal/vite/dev-entry.mjs (2)
  • ws (12-14)
  • nitroApp (8-8)
src/presets/cloudflare/runtime/_module-handler.ts (2)
src/runtime/internal/vite/dev-entry.mjs (1)
  • nitroApp (8-8)
src/types/srvx.ts (1)
  • ServerRequest (1-1)
🔇 Additional comments (3)
src/presets/cloudflare/runtime/cloudflare-module.ts (1)

27-29: LGTM! WebSocket upgrade correctly uses augmented request.

The upgrade path now receives cfRequest (which has been augmented with Cloudflare env/context in the parent handler), achieving the PR's goal of making Cloudflare bindings accessible in WebSocket handlers.

src/presets/cloudflare/runtime/cloudflare-durable.ts (2)

5-5: LGTM! Import correctly added.

The augmentReq import is necessary for augmenting requests in the $DurableObject.fetch method.


76-82: Excellent refactoring! Context augmentation is correctly positioned.

The key change is calling augmentReq(request, this.env, this.ctx) at the start of the method, ensuring the request carries Cloudflare env and context before any handler logic runs. This achieves the PR's goal of making Cloudflare bindings accessible in WebSocket handlers.

The simplified flow using nitroApp.fetch(request) is cleaner and more maintainable than the previous approach.

Comment thread src/presets/cloudflare/runtime/_module-handler.ts
@pi0 pi0 changed the title feat: always augment request with cf context feat(cloudflare): always augment request with cf context Jan 9, 2026
Copy link
Copy Markdown
Member

@pi0 pi0 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! Made few adjustments, after this, req.runtime. and peer.req.runtime. both should work always.

We might need some follow-up fixes in crossws too. When a durable instance is hydrated, crossws makes a new fallback req here (since the original is only on first wake) and we need to inject context to it.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
src/presets/cloudflare/runtime/_module-handler.ts (1)

113-126: Well-structured augmentation helper.

The augmentReq function correctly:

  • Initializes the runtime object with fallback values
  • Preserves existing cloudflare properties via spread (line 121)
  • Binds waitUntil for proper async handling
  • Supports both ExecutionContext and DurableObjectState

The multiple as any casts (lines 118, 122-123) bridge type systems between Cloudflare Workers types and internal types, which is necessary in this runtime boundary layer.

♻️ Optional: Consider stronger typing

If stricter typing would be valuable, you could define an explicit type guard or interface for ServerRequest with Cloudflare extensions:

interface CloudflareServerRequest extends ServerRequest {
  runtime: {
    name: string;
    cloudflare?: {
      env?: unknown;
      context?: CF.ExecutionContext | CF.DurableObjectState;
    };
  };
  waitUntil?: (promise: Promise<any>) => void;
}

export function augmentReq(
  cfReq: Request | CF.Request,
  env: unknown,
  context: CF.ExecutionContext | CF.DurableObjectState
) {
  const req = cfReq as CloudflareServerRequest;
  // ... rest of implementation
}

However, the current approach is pragmatic for runtime code where type boundaries are fluid.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e6970aa and 72d9d85.

📒 Files selected for processing (1)
  • src/presets/cloudflare/runtime/_module-handler.ts
🧰 Additional context used
📓 Path-based instructions (2)
src/**/*.{ts,js,tsx,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

src/**/*.{ts,js,tsx,jsx}: Use pathe for cross-platform path operations instead of Node.js node:path
Use ESM and modern JavaScript
Do not add comments explaining what the line does unless prompted

Files:

  • src/presets/cloudflare/runtime/_module-handler.ts
src/**/*.{ts,js}

📄 CodeRabbit inference engine (AGENTS.md)

Use unstorage for storage abstraction

Files:

  • src/presets/cloudflare/runtime/_module-handler.ts
🧠 Learnings (3)
📚 Learning: 2025-12-24T11:45:17.435Z
Learnt from: CR
Repo: nitrojs/nitro PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-24T11:45:17.435Z
Learning: Applies to src/runtime/**/*.{ts,js} : In runtime code, prefer Web APIs (fetch, Request, Response, URL, etc.) over Node.js APIs

Applied to files:

  • src/presets/cloudflare/runtime/_module-handler.ts
📚 Learning: 2025-12-24T11:45:17.435Z
Learnt from: CR
Repo: nitrojs/nitro PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-24T11:45:17.435Z
Learning: Applies to src/runtime/**/*.{ts,js} : Keep runtime code minimal and side-effect free to reduce bundle size

Applied to files:

  • src/presets/cloudflare/runtime/_module-handler.ts
📚 Learning: 2025-12-03T19:09:13.905Z
Learnt from: medz
Repo: nitrojs/nitro PR: 3834
File: src/presets/cloudflare/server-entry.ts:63-63
Timestamp: 2025-12-03T19:09:13.905Z
Learning: In the Nitro Cloudflare preset (src/presets/cloudflare/server-entry.ts), native errors from oxc-parser and Node.js readFile operations should be allowed to bubble up naturally without wrapping, as their native error messages are more user-friendly and provide better diagnostic information.

Applied to files:

  • src/presets/cloudflare/runtime/_module-handler.ts
🧬 Code graph analysis (1)
src/presets/cloudflare/runtime/_module-handler.ts (2)
src/runtime/internal/vite/dev-entry.mjs (1)
  • nitroApp (8-8)
src/types/srvx.ts (1)
  • ServerRequest (1-1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: tests-rolldown (windows-latest)
🔇 Additional comments (2)
src/presets/cloudflare/runtime/_module-handler.ts (2)

24-25: LGTM! Request augmentation happens early in the lifecycle.

The global __env__ assignment and augmentReq call ensure that Cloudflare context is available before any downstream processing, including WebSocket upgrades. This addresses the PR objective.


38-38: LGTM! Simplified control flow.

The direct return of nitroApp.fetch(request) is cleaner than the previous local fetchHandler, and the request already includes the augmented Cloudflare context from line 25.

@pi0 pi0 merged commit 99691fc into nitrojs:main Jan 9, 2026
7 of 8 checks passed
@emretinaztepe emretinaztepe deleted the fix/cloudflare-ws-context branch January 9, 2026 10:15
@emretinaztepe
Copy link
Copy Markdown
Contributor Author

@pi0 Thank you! Not sure if it is the right place to share it, but another major issue that is on more than a dozen forums, unsolved, is that Nitro does not provide any mechanism to export Durable Objects. This prevents the use of Durable Objects in Nitro and Nuxt in dev mode. Are there any plans to address this issue? Cloudflare Workers expect DOs to be exported, and the below workaround makes it work in Nuxt preview/build mode, but after two months of research, I had no luck getting it to work in dev mode.

Below is the only workaround I was able to make it work for preview/build mode by setting wrangler's main property to "server/worker.ts"
worker.ts

Any update or future roadmap info would be useful.

@pi0
Copy link
Copy Markdown
Member

pi0 commented Jan 9, 2026

We recently supported exports.cludflare.ts entry (see #3834)

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.

2 participants