Skip to content

Propuesta: Abstracción nativa/wrapper en Express para simplificar el manejo de respuestas SSE (Server-Sent Events) #7334

Description

@danelmott

actualmente estoy realizando un proyecto con express, no quiero usar websockets porque solo es un endpoint específico de mi app de express que necesita que se muestre la información en tiempo real, entonces una alternativa para ello es usar sse, que es también http pero da un funcionamiento parecido al de websocket, el problema es que implementarlo requiere un setup bastante riguroso en node, siento que se podría crear una abstracción en express para hacerlo mas facil asi como con las respuestas y esas cosas, porque actualmente para poder implementarlo tengo que configurar varios headers y el sistema de envió que siento que express puede simplificar mucho creando un wrapper para el envio de respuestas con sse, aqui adjunto un ejemplo del codigo que uso en mi app el cual es un wrapper para enviar respuestas por sse de manera facil

function handlePreStreamError(res, error) {
    if (res.headersSent) {
        sendSse(res, {
            type: "error",
            code: error.code || "SERVER_INTERNAL_ERROR",
            message: error.message || "Error interno del servidor",
        });
        return res.end();
    }

    return sendDomainError(res, error);
}

function sendSse(res, payload) {
    res.write(`data: ${JSON.stringify(payload)}\n\n`);
    res.flush?.();
}

function setupSse(res) {
    res.setHeader('Content-Type', 'text/event-stream; charset=utf-8');
    res.setHeader('Cache-Control', 'no-cache, no-transform');
    res.setHeader('Connection', 'keep-alive');
    res.setHeader('X-Accel-Buffering', 'no');
    res.flushHeaders?.();
}

ejemplo de uso relativo:

async function streamResponseController(req, res) {
    try {
        setupSse(res);

        sendSse(res, { type: "start", message: "Iniciando proceso..." });

        const data = await mockDataFunction(req.body);

        for await (const chunk of data) {
            if (res.writableEnded || req.aborted) {
                break;
            }

            sendSse(res, {
                type: "chunk",
                data: chunk,
            });
        }

        sendSse(res, { type: "done" });
        res.end();

    } catch (error) {
        handlePreStreamError(res, error);
    }
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions