Welcome to the Linux Foundation Forum!

Lab 4.2 - Stream some content

Options

Hi,
In lab 4.2, I'm trying this:

The reply.send method can also be passed a stream and Fastify behaves in the same >way - by piping the stream as the HTTP response."

but I don't get it

const dataStream = require('./../../stream');

module.exports = async function (fastify, opts) {
  fastify.get('/', async function (request, reply) {
    reply.send(dataStream);
  })
}

I have also tried with this

const dataStream = require('./../../stream');

module.exports = async function (fastify, opts) {
  fastify.get('/', async function (request, reply) {
    reply.header('Content-Type', 'application/octet-stream');
    reply.send(dataStream);
  })
}

Anyone can help me?

Thanks in advance.

Comments

  • Hi,

    I have found the answer

    'use strict'
    
    const stream = require('./../../stream');
    
    module.exports = async function (fastify, opts) {
      fastify.get('/', async function (request, reply) {
        reply.headers({'content-type': 'text/html' });
        await reply.send(stream());
      })
    }
    

    but I don't understand totally why this is working.

    Why I have to await for reply?

    Thanks

  • xdxmxc
    xdxmxc Posts: 139
    Options

    it's not about the await - you were passing a function, now you're passing a stream. Note that you're CALLING stream() in your working example

  • arturo.miguel.next
    edited November 2022
    Options

    Hi @xdxmxc,

    Without await it doesn't work

    'use strict'
    
    const stream = require('./../../stream');
    
    module.exports = async function (fastify, opts) {
      fastify.get('/', async function (request, reply) {
        reply.headers({'content-type': 'text/html' });
        reply.send(stream());
      })
    }
    
  • krave
    krave Posts: 58
    edited November 2022
    Options

    Hi, @arturo.miguel.next ,

    You can remove both await and async for the route handler.

    Like this:

    'use strict'
     
    const stream = require('./../../stream');
    
    module.exports = async function (fastify, opts) {
        fastify.get('/', function (request, reply) {
            reply.type('text/html');
            reply.send(stream());
        })
    }
    

    The reason why your async version handler doesn't work without await maybe the internal mechanism of fastify I guess.

    According to your code, here is an equivalent code with implicit return:

        'use strict'
         
        const stream = require('./../../stream');
         
        module.exports = async function (fastify, opts) {
          fastify.get('/', async function (request, reply) {
            reply.headers({'content-type': 'text/html' });
            reply.send(stream());
            return; // this is an implicit
          })
        }
    

    The implicit return notifies fastify that this async function is already over. Fastify does not necessarily need to wait anything else to finish the response. The possible hypothesis might be "Hey, it is already an async handler. If there is anything I need to wait, why would it already returned. It totally could wait inside the function and return lately".

    When you add the await before reply.send(stream()), the handler will wait reply.send(stream()) to finish before return the function. Then end the HTTP response.

    You can verify by this:

    'use strict'
    
    const stream = require("../../stream")
    
    module.exports = async function (fastify, opts) {
        fastify.get('/', async function (request, reply) {
            reply.type('text/html');
            reply.send(stream());
            return "Hi, I am Krave."
        })
    }
    

    You will see that the response to client finishes immediately without any delay.

  • xdxmxc
    xdxmxc Posts: 139
    edited December 2022
    Options

    yes @krave is exactly right. Regarding the await, when the route handler returns a promise (as all async functions do) the resolution of the promise determines when the route has been completely handled - not the stream passed to reply send, however the promise returned from reply.send can be awaited in this case to ensure the promise resolves after the stream completes. While this seems clunky it's merely supporting an edge-case, it's better not to mix reply.send and async route functions. So in practice you can either go the way @krave shows OR you avoid reply.send and instead return the stream (or whatever value) from the function (should work async or not).

Categories

Upcoming Training