fastify / fastify-reply-from

fastify plugin to forward the current http request to another server
MIT License
150 stars 76 forks source link

Async onResponse #380

Open sumbad opened 2 weeks ago

sumbad commented 2 weeks ago

Prerequisites

Issue

Hello! Can someone clarify is it possible or not using async onResponse hook with @fastify/reply-from plugin? Sometimes with async onResponse in my logs I see error:

"stack":"FastifyError: Reply was already sent, did you forget to return reply
 at Reply.send (/node_modules/fastify/lib/reply.js:151:26)
 at /node_modules/@fastify/reply-from/index.js:205:14
 at /node_modules/@fastify/reply-from/index.js:284:9
 at /node_modules/@fastify/reply-from/lib/request.js:177:7
 at RequestHandler.runInAsyncScope (node:async_hooks:203:9)
 at RequestHandler.onHeaders (/node_modules/@fastify/reply-from/node_modules/undici/lib/api/api-request.js:104:14)
 at Request.onHeaders (/node_modules/@fastify/reply-from/node_modules/undici/lib/core/request.js:275:29)
 at Parser.onHeadersComplete (/node_modules/@fastify/reply-from/node_modules/undici/lib/client.js:920:27)
 at wasm_on_headers_complete (/node_modules/@fastify/reply-from/node_modules/undici/lib/client.js:536:30)
 at wasm://wasm/0003626a:wasm-function[11]:0x494
 at wasm://wasm/0003626a:wasm-function[51]:0x1003
 at wasm://wasm/0003626a:wasm-function[68]:0x6e8e
 at wasm://wasm/0003626a:wasm-function[67]:0x1568
 at wasm://wasm/0003626a:wasm-function[21]:0x552
 at Parser.execute (/node_modules/@fastify/reply-from/node_modules/undici/lib/client.js:677:22)
 at Parser.readMore (/node_modules/@fastify/reply-from/node_modules/undici/lib/client.js:646:12)","code":"FST_ERR_REP_ALREADY_SENT","name":"FastifyError","statusCode":500},"msg":"Reply was already sent, did you forget to return reply

My goal is changing a response body:

    // Proxy to another Api
    return reply.from(proxyPath, {
      rewriteRequestHeaders() {
        return proxyHeaders;
      },
      rewriteHeaders(headers) {
        return createProxyHeaders(proxyUrl, headers);
      },
      async onResponse(_req, reply, res) {
        const resBody = await new Promise((resolve, reject) => {
          let buffer = Buffer.from('', 'utf8');

          res.on('data', (chunk) => (buffer = Buffer.concat([buffer, chunk])));

          res.on('end', async () => {
            resolve(buffer.toString());
          });

          res.on('error', (error) => {
            reject(error);
          });
        });

        // do something with resBody

       return reply.send(resBody);
     }
climba03003 commented 2 weeks ago

I don't think we support async-await in onResponse hook.

sumbad commented 2 weeks ago

Thanks for your reply! Is there a way to get the response body from the upstream server and modify it before reply? I've used https://github.com/fastify/fastify-reply-from/issues/265 like an example, but there is async onResponse.