Aplicando as streams em um servidor HTTP


Após entender com funcionam os vários tipos de streams do Node, vamos aplicá-las de forma um pouco mais palpável em um servidor HTTP.

Primeiramente vamos criar um servidor HTTP na porta 3001.

import http from 'node:http'
 
const server = http.createServer((request, response) => {})
 
server.listen(3001)

Em seguida, vamos criar uma arquivo que será responsável por simular o envio dos dados de larga escala para o servidor acima. Para isso, podemos utilizar a Fetch API para enviar os dados para ele no formato de stream de dados.

import { Readable } from 'node:stream'
 
class OneToHundredStream extends Readable {
    index = 1
 
    _read() {
        const i = this.index++
 
        setTimeout(() => {
            if (i > 100) {
                this.push(null)
            } else {
                const buf = Buffer.from(String(i))
                this.push(buf)
            }
        }, 1_000)
    }
}
 
fetch('http://localhost:3001', {
    method: 'POST',
    body: new OneToHundredStream(),
    duplex: 'half'
})

Além disso, implementaremos a stream de transformação responsável por receber os dados de entradas e invertê-los.

import { Transform } from 'node:stream'
 
 
class InverseNumberStream extends Transform {
    _transform(chunk, encoding, callback) {
        const transformed = Number(chunk.toString()) * -1
 
        console.log(transformed)
 
        callback(null, Buffer.from(String(transformed)))
    }
}

Após isso, criar utilizar das portas de entrada e saída do Node (request e response, respectivamente) para podermos inverter os dados de entrada e retornar para o cliente.

const server = http.createServer((request, response) => {
	return request.pipe(new InverseNumberStream()).pipe(response)
})

Desse modo, ao subirmos o servidor e em seguida executar o arquivo que simula o envio dos dados:

$ node src/stream-http-server.js
$ node src/fake-upload-to-http-stream.js

Temos a seguinte saída nos logs do servidor:

-1
-2
-3
-4
-5
-6
-7
-8
...

Referências