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

A way to completly overwrite response from middleware after next() #960

Closed
TorbjornHoltmon opened this issue Mar 6, 2023 · 5 comments
Closed

Comments

@TorbjornHoltmon
Copy link

TorbjornHoltmon commented Mar 6, 2023

This is a very niche issue.

We use Hono for many things, including our Cloudflare workers' proxy.
The proxy sits on top of our domain and routes traffic to different workers and other external servers.

When you proxy a request from a worker, the response that Hono gets is a fetch response, and you cannot change headers.

When we use middleware in our proxy, there is no way for us to re-write the response since ´contex.res´ has a set that manipulates the headers.

https://github.com/honojs/hono/blob/fea78f29bd681350ce61dd71b33042aa6ec7db5c/src/context.ts#LL101-L110C4

  set res(_res: Response) {
    if (this._res) {
      this._res.headers.delete('content-type')
      this._res.headers.forEach((v, k) => {
        _res.headers.set(k, v)
      })
    }
    this._res = _res
    this.finalized = true
  }

Not many people will have this issue, but we could really use some type of overwrite on the response so that we can write middleware that does something like this:

export const cookieMiddleware: MiddlewareHandler<HonoEnv> = async (c, next) => {
    await next()
    if(c.res.headers.has("special-header")) {
      // We cannot use res.headers, so we clone the headers
      const clonedHeaders = cloneResponseHeaders(c.res)
      clonedHeaders.append('Set-Cookie', "cookie goes here")
        
      // create a new response from the old
      const newResponse = new Response(c.res.body, {
        headers: clonedHeaders,
        status: c.res.status,
      })
      // some way to overwrite response, just an example
      c.overwriteResponse(newResponse)
    }
}

If only the set did not change headers we could have used that

 set res(_res: Response) {
    this._res = _res
    this.finalized = true
  }

Maybe this is something that should be contained in its own world. "hono/proxy". Which is meant to handle things as a proxy and not api.

@yusukebe
Copy link
Member

yusukebe commented Mar 7, 2023

Hi @TorbjornHoltmon !

I have ideas about this "middleware matter". I'll let you know later.

@yusukebe
Copy link
Member

Hi @TorbjornHoltmon !

I've created PR #970 . With this PR, you can do it by putting undefined:

app.use('*', async (c, next) => {
  await next()
  c.res = undefined
  c.res = new Response('New Response')
})

This way does not include breaking changes and makes it possible what you want to do.

@yusukebe
Copy link
Member

yusukebe commented Aug 3, 2023

I think we can close this issue. Thanks.

@yusukebe yusukebe closed this as completed Aug 3, 2023
@fzn0x
Copy link
Contributor

fzn0x commented Apr 26, 2024

Hi, can you document this feature ? @yusukebe I think this is really helpful for custom middleware. I just found the feature was implemented here.

@yusukebe
Copy link
Member

Hi @fzn0x

Created the issue honojs/website#317 on the website repo. We'll do that.

This issue was closed.
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