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 method to send request to self #1677

Open
nicksrandall opened this issue Nov 9, 2023 · 8 comments
Open

Context method to send request to self #1677

nicksrandall opened this issue Nov 9, 2023 · 8 comments

Comments

@nicksrandall
Copy link
Contributor

Sometimes in a view route, I want to call an another route handler to get data. It would be awesome if Hono has this built in.

Runtimes like Cloudflare workers do not allow workers to "fetch" themselves over the network so this would be a nice work around that would allow hono to skip the network entirely and just call itself.

Proposed API

const app = new Hono():

app.get("/api/data", async c => {
  // get some data
  return c.json(data);
});

app.get("/view", async c => {
  const resp = await c.fetch("/api/data", c.req.raw); // follows `Fetch` API
  const data = await resp.json();
  return c.render(<SomeComponent data={data} />);
});

I'd be happy to send a PR if maintainers are open to this change.

Originally posted by @nicksrandall in #1675

@yusukebe
Copy link
Member

Hi, @nicksrandall

I think we can do it with this code:

app.get('/api', (c) => {
  return c.json({ foo: 'bar' })
})

app.get('/', async (c) => {
  const res = await app.request('/api')
  return c.json(await res.json())
})

@nicksrandall
Copy link
Contributor Author

nicksrandall commented Nov 13, 2023

Thanks for responding @yusukebe

As I understand it, that code does not keep track of the execution context or environment variables so it doesn't work for my use-case.

@nicksrandall
Copy link
Contributor Author

nicksrandall commented Nov 14, 2023

@yusukebe to be more specific, the code you suggest does work for very simple use-cases but it doesn't not work if the API route is using ENV variables or execution context (in a cloudflare worker). That is why I think it makes sense for a new method to live on the "context" because we want to execute the handler with the current context. While I think c.fetch(...) name makes the most sense to me, we could just as easily name the method c.request(...) if you felt like that was more consistent. Thoughts?

If we made that change, your example would look something like this:

app.get('/api', (c) => {
  return c.json({ foo: 'bar' })
})

app.get('/', async (c) => {
  const res = await c.request('/api')
  return c.json(await res.json())
})

Again thanks for your help with this!

@yusukebe
Copy link
Member

I'm not run it yet, but I think this would work with ENV:

app.get('/', (c) => {
  app.request('/api', c.req.raw, c.env)
  return c.json(0)
})

@nicksrandall
Copy link
Contributor Author

@yusukebe Your suggestion does pass provides the env variables but it still doesn't pass the execution context.

@yusukebe
Copy link
Member

yusukebe commented Dec 5, 2023

Hi.

You can also pass the execution context like the following:

app.request('/api', c.req.raw, c.env, c.executionCtx)

@Zerebokep
Copy link

That works, however, this error is thrown in the console:

Your worker created multiple branches of a single stream (for instance, by calling response.clone()orrequest.clone()) but did not read the body of both branches. This is wasteful, as it forces the system to buffer the entire stream of data in memory, rather than streaming it through. This may cause your worker to be unexpectedly terminated for going over the memory limit. If you only meant to copy the request or response headers and metadata (e.g. in order to be able to modify them), use the appropriate constructors instead (for instance, new Response(response.body, response), new Request(request), etc).

@yusukebe
Copy link
Member

yusukebe commented Feb 8, 2024

@Zerebokep

That warning is annoying, but you can ignore it.

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

No branches or pull requests

3 participants