Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

context c.set/get not working in cloudflare pages functions #3320

Closed
zoubingwu opened this issue Aug 24, 2024 · 7 comments · Fixed by #3332
Closed

context c.set/get not working in cloudflare pages functions #3320

zoubingwu opened this issue Aug 24, 2024 · 7 comments · Fixed by #3332
Labels

Comments

@zoubingwu
Copy link

zoubingwu commented Aug 24, 2024

What version of Hono are you using?

4.5.8

What runtime/platform is your app running on?

cloudflare pages

What steps can reproduce the bug?

made a minimal repro here: https://github.com/zoubingwu/hono-ctx-set-cf-pages

git clone https://github.com/zoubingwu/hono-ctx-set-cf-pages.git
pnpm install
pnpm run dev

then open http://localhost:8888/, you will see alert with hello undefined

What is the expected behavior?

should be hello joe since it was set in middleware

What do you see instead?

hello undefined

Additional information

// functions/_middleware.ts
import { handleMiddleware } from "hono/cloudflare-pages";

export const onRequest = [
  handleMiddleware(async (c, next) => {
    console.log("middleware setting user");
    c.set('user', 'joe')
    await next();
  })
]

// functions/api/[[route]].ts
import { Hono } from "hono";
import { handle } from "hono/cloudflare-pages";

interface HonoContext {
  Variables: {
    user: string
  };
}

const app = new Hono<HonoContext>().basePath('/api');

const routes = app.get('/hello', (c) => {
  return c.json({
    message: `Hello, ${c.get('user')}!`
  });
});

export const onRequest = handle(routes);


// index.html
fetch('/api/hello').then(res => res.json()).then(data => {
    alert(data.message)
})
@yusukebe
Copy link
Member

Hi @zoubingwu

Thank you for creating the issue. This looks like a bug, but it's a known issue that can be resolved because a Context in Pages Middleware is not shared for the handler. This is a limitation for using Cloudfare Pagea Middleware.

If you want to do more complex things for Cloudflare Pages, you can try the Cloudflare Pages starter template:

npm create hono@latest -- --template cloudflare-pages

@zoubingwu
Copy link
Author

zoubingwu commented Aug 25, 2024

@yusukebe cf context prodvides a data object to attach some data and will persist during the request, their docs didn't mention that clearly tho but it works

see https://developers.cloudflare.com/pages/functions/api-reference/#eventcontext and https://community.cloudflare.com/t/what-is-context-data-in-pages-functions/476559

can we use that instead? I found that this object is not accessible in hono's context.

I updated the code in the reproduce repo, you can check it out.

// _middleware.ts
export const onRequest = [
  // handleMiddleware(async (c, next) => {
  //   console.log("middleware setting user");
  //   c.set('user', 'joe');
  //   console.log(c);
  //   c.env.eventContext.data.user = 'joe2' // not working
  //   return await next();
  // })
  async (context) => {
    context.data.user = "joe"; // working
    return await context.next();
  },
];

// [[route]].ts
const routes = app.get("/hello", (c) => {
  return c.json({
    //@ts-ignore
    message: `Hello, ${c.env.eventContext.data.user}!`,
  });
});

@yusukebe
Copy link
Member

Hi @zoubingwu

Exactly. Cloudflare Pages provides data. Nice suggestion. I'll consider it.

Hi @BarryThePenguin If you have any thoughts, please share them.

@BarryThePenguin
Copy link
Contributor

BarryThePenguin commented Aug 26, 2024

I'd expect this to work..

handleMiddleware(async (c, next) => {
  console.log("middleware setting user");
  c.set('user', 'joe');
  console.log(c);
- c.env.eventContext.data.user = 'joe2' // not working
+ c.executionCtx.data.user = 'joe2' // should work
  return await next();
})

The Cloudflare EventContext is passed to new Context() and can be accessed through the executionCtx property. However the types don't allow for this..

const context = new Context(executionCtx.request, {
env: executionCtx.env,
executionCtx,
})

this.#executionCtx = options.executionCtx

@BarryThePenguin
Copy link
Contributor

I can see a solution where using c.get() and c.set() update the underlying c.executionCtx.data property, but making the types work might be tricky..

@zoubingwu
Copy link
Author

according to #1219, if we use AsyncLocalStorage for context, will this simplifies the typings?

@yusukebe
Copy link
Member

This is closed by #3332!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants