elysiajs / elysia

Ergonomic Framework for Humans
https://elysiajs.com
MIT License
10.25k stars 219 forks source link

Streaming responses #250

Closed jmandel closed 11 months ago

jmandel commented 1 year ago

Is there some mechanism to return a stream? Say I want to write a function that calls fetch and returns the fetch's response body, without accumulating the full body in memory?

Sorry if this is something obvious; from the docs and types.ts I'm having trouble seeing how this is covered.

bogeychan commented 1 year ago

Hi 👋

this should do it, see:

import { Elysia } from 'elysia';

const app = new Elysia()
  .get('/', () => fetch('https://github.com/elysiajs/elysia/issues/250'))
  .listen(3000);

console.log(`Listening on http://${app.server!.hostname}:${app.server!.port}`);

Or with custom Stream:

app.get(
  '/',
  () =>
    new Response(
      new ReadableStream({
        pull(controller) {
          controller.enqueue('Hello world!');

          controller.close();
        }
      })
    )
);
jmandel commented 1 year ago

Thanks so much! It might be worth including a link out to the definition of the response object in the documentation at https://elysiajs.com/concept/handler.html#response ; I did not realize this would be a standard like https://developer.mozilla.org/en-US/docs/Web/API/Response or similar.

emilianomon commented 1 year ago

Any tips on how to document the response?

I am using the Swagger plugin and it does not seem to exist a way to do it using Typebox.

crishoj commented 12 months ago

@emilianomon, you mean this? → https://elysiajs.com/patterns/creating-documentation.html#route-definitions

emilianomon commented 11 months ago

Since there is no way to relate the returning type of the streaming write call with the actual handler method, the question was wrongfully posed.

Is there a way to inject a streaming helper that actually takes de response validation type into consideration?

My end goal is to have a typeface streaming emit.

SaltyAom commented 11 months ago

Closing with the introduction of Stream plugin.

emilianomon commented 11 months ago

Perfect. Just for another round of clarification, I thought of something like the following:

import Elysia, { t } from 'elysia';
import { stream } from '@elysiajs/stream';

const handler = new Elysia();

handler
use(stream)
.post('/stream', ({ stream }) => {

  stream.send({
    validatedAttribute: true, // This should be validated and typesafe.
  });

  return stream;
}, {
  response: t.Object({
      validatedAttribute: t.Boolean(),
  }),
});

export { handler as streamHandler };

Or even a custom stream validation like:

// ...
}, {
  stream: t.Object({
      validatedAttribute: t.Boolean(),
  }),
});
// ...

A stream helper injection that takes into consideration the response validation seems to me like a great addition!

Does it make sense @SaltyAom?