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);
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions