Streaming de dados em HTTP

Embora não seja um tópico tão falado, é possível sim fazer streaming de dados puramente com HTTP. Há alguns métodos diferentes:

Método Transfer-Encoding: chunked

Funciona apenas no HTTP 1.1

O cabeçalho que define um Transfer-Encoding é

Transfer-Encoding: chunked

Mais informações no artigo da MDN.

Para o Python, este método funciona bem com o aiohttp. Não funciona com Flask e Python, pois o cabeçalho Transfer-Encoding quebra o padrão WSGI.

Método SSE (Server Sent Events) (Event Stream)

Funciona em HTTP 1.1 e HTTP 2

O cabeçalho que define um SSE é

Content-Type: text/event-stream

Do lado do JavaScript, a Classe (também chamam de API) que lida com os SSE é a EventSource.

Explicação de SSE da OReilly
https://www.oreilly.com/library/view/high-performance-browser/9781449344757/ch16.html

Tutorial usando Python e Flask
https://medium.com/code-zen/python-generator-and-html-server-sent-events-3cdf14140e56

Exemplo de Event Stream em Go
https://gist.github.com/fiorix/f58c6f8b2a8b23521a47

Usando o EventSource API do JavaScript
https://hpbn.co/server-sent-events-sse/

Criando SSE no Spring
https://www.baeldung.com/spring-server-sent-events

Método WebSocket

Não usa exatamente o HTTP, mas é uma alternativa.

O seu ponto positivo é que é bi-direcional.

Método Long Polling

Não é recomendado. Gera muito overhead, mas é um pseudo streaming compatível com protocolos antigos do HTTP (anteriores ao HTTP 1.1).

Streaming via Partial Content

É uma forma comum de fazer streaming de dados de mídia (áudio e vídeos) usando HTTP 1.1.

A cada mensagem enviada pelo servidor, vemos em seu cabeçalho o código HTTP 206 Partial Content.

Exemplo:

Request:

Request URL: https://t4.bcbits.com/stream/d395e9d9e2024208e1e56881ab97526c/mp3-128/213275318?p=0&ts=1584762263&t=5bc9c67fe19303967d4cd011b59ff2003c407e39&token=1584762263_4f450e24db979391dc6dfa1b2eaa0946e2880533Request Method: GETStatus Code: 206 Partial ContentRemote Address: 151.101.1.5:443Referrer Policy: no-referrer-when-downgrade

Accept: */*Accept-Encoding: identity;q=1, *;q=0Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6Connection: keep-aliveHost: t4.bcbits.comIf-Range: Wed, 06 Feb 2019 23:36:57 GMTRange: bytes=6946816-9039619Referer: https://lustre.bandcamp.com/album/another-time-another-place-chapter-oneSec-Fetch-Dest: audioSec-Fetch-Mode: no-corsSec-Fetch-Site: cross-siteUser-Agent: Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36

p: 0ts: 1584762263t: 5bc9c67fe19303967d4cd011b59ff2003c407e39token: 1584762263_4f450e24db979391dc6dfa1b2eaa0946e2880533

Response:

Accept-Ranges: bytesAccept-Ranges: bytesAge: 69682Cache-Control: max-age=31536000Content-Length: 2092804Content-Range: bytes 6946816-9039619/9039620Content-Type: audio/mpegDate: Fri, 20 Mar 2020 03:50:00 GMTLast-Modified: Wed, 06 Feb 2019 23:36:57 GMTVia: 1.1 varnishVia: 1.1 varnishX-Cache: HIT, HITX-Cache-Hits: 0, 0X-Served-By: cache-mdw17382-MDW, cache-gru17151-GRUX-Timer: S1584676200.410166,VS0,VE0

Uma forma eficiente de fazer streaming de mídias é usando o software de cache HTTP Varnish.

Outra ideia é usar um CDN mesmo.

Referências

Uma resposta super útil
https://dev.to/anoff/how-to-create-a-streaming-http-interface-in-python--ceh

Discussão SSE vs Chunked Streaming
https://stackoverflow.com/questions/39889052/why-use-server-sent-events-instead-of-simple-http-chunked-streaming

You should also read: