Skip to content

Cloudflare binding issue #4179

@Joeldorne

Description

@Joeldorne

Environment

I couldn't get this code to work as there's no data on 'event.req.runtime.cloudflare'. The proxy wasn't loading for me.


defineHandler(async (event) => {
  const { env } = event.req.runtime.cloudflare
  const stmt = await env.MY_D1.prepare('SELECT id FROM table')
  const { results } = await stmt.all()
})```


I added this code to the Cloudflare Proxy to debug and fix the issues:


```import { useRuntimeConfig } from "nitro/runtime-config";  
  
const proxy = await _getPlatformProxy().catch((error) => {  
  console.error("[Cloudflare Dev] Failed to initialize wrangler bindings proxy", error);  
  console.error("[Cloudflare Dev] Error details:", {  
    message: error.message,  
    stack: error.stack,  
    code: error.code  
  });  
  return _createStubProxy();  
});  
  
console.log("[Cloudflare Dev] Proxy initialized successfully");  
console.log("[Cloudflare Dev] Available env keys:", Object.keys(proxy.env));  
  
globalThis.__env__ = proxy.env;  
globalThis.__wait_until__ = proxy.ctx.waitUntil.bind(proxy.ctx);  
  
const cloudflareDevPlugin = function(nitroApp) {  
  console.log("[Cloudflare Dev] Plugin initializing");  
    
  nitroApp.hooks.hook("request", async (event) => {  
    try {  
      console.log("[Cloudflare Dev] Request hook executing for:", event.path);  
        
      event.req.context ??= {};  
        
      // Initialize runtime if it doesn't exist  
      if (!event.req.runtime) {  
        event.req.runtime = {};  
      }  
        
      // Set runtime name  
      event.req.runtime.name = "cloudflare";  
        
      // Inject cloudflare runtime with proper merging  
      event.req.runtime.cloudflare = {  
        ...(event.req.runtime.cloudflare || {}),  
        env: proxy.env,  
        context: proxy.ctx,  
      };  
        
      // Also inject into context for compatibility  
      event.req.context.cloudflare = {  
        ...(event.req.context.cloudflare || {}),  
        request: event.req,  
        env: proxy.env,  
        context: proxy.ctx,  
      };  
        
      // Bind waitUntil  
      event.req.waitUntil = proxy.ctx.waitUntil.bind(proxy.ctx);  
      event.req.cf = proxy.cf;  
        
      console.log("[Cloudflare Dev] Runtime injected successfully");  
      console.log("[Cloudflare Dev] Env keys in request:", Object.keys(proxy.env));  
    } catch (error) {  
      console.error("[Cloudflare Dev] Error in request hook:", error);  
    }  
  });  
  
  // Dispose proxy when Nitro is closed  
  nitroApp.hooks.hook("close", () => {  
    console.log("[Cloudflare Dev] Disposing proxy");  
    return proxy?.dispose();  
  });  
};  
  
export default cloudflareDevPlugin;  
  
async function _getPlatformProxy() {  
  const pkg = "wrangler"; // bypass bundler  
  const { getPlatformProxy } = (await import(/* @vite-ignore */ pkg).catch(() => {  
    throw new Error(  
      "Package `wrangler` not found, please install it with: `npx nypm@latest add -D wrangler`"  
    );  
  }));  
  
  const runtimeConfig = useRuntimeConfig();  
  
  const proxyOptions = {  
    configPath: runtimeConfig.wrangler?.configPath,  
    persist: { path: runtimeConfig.wrangler?.persistDir },  
  };  
    
  if (runtimeConfig.wrangler?.environment) {  
    proxyOptions.environment = runtimeConfig.wrangler.environment;  
  }  
    
  console.log("[Cloudflare Dev] Initializing platform proxy...");  
  console.log("[Cloudflare Dev] Runtime config:", runtimeConfig.wrangler);  
  console.log("[Cloudflare Dev] Proxy options:", proxyOptions);  
    
  const wrangler = await import(pkg);  
  console.log("[Cloudflare Dev] Wrangler imported successfully");  
    
  const proxy = await getPlatformProxy(proxyOptions);  
  console.log("[Cloudflare Dev] Platform proxy created successfully");  
    
  return proxy;  
}  
  
function _createStubProxy() {  
  console.warn("[Cloudflare Dev] Using stub proxy - Wrangler proxy failed to initialize");  
    
  return {  
    env: {},  
    cf: {},  
    ctx: {  
      waitUntil() {},  
      passThroughOnException() {},  
      props: {},  
    },  
    caches: {  
      open() {  
        const result = Promise.resolve(new _CacheStub());  
        return result;  
      },  
      get default() {  
        return new _CacheStub();  
      },  
    },  
    dispose: () => Promise.resolve(),  
  };  
}  
  
class _CacheStub {  
  delete() {  
    const result = Promise.resolve(false);  
    return result;  
  }  
    
  match() {  
    const result = Promise.resolve(undefined);  
    return result;  
  }  
    
  put() {  
    const result = Promise.resolve();  
    return result;  
  }  
}```

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions