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: GET Status Code: 206 Partial Content Remote Address: 151.101.1.5:443 Referrer Policy: no-referrer-when-downgrade
Accept: */*Accept-Encoding: identity;q=1, *;q=0 Accept-Language: pt-BR,pt;q=0.9,en-US;q=0.8,en;q=0.7,es;q=0.6 Connection: keep-alive Host: t4.bcbits.com If-Range: Wed, 06 Feb 2019 23:36:57 GMT Range: bytes=6946816-9039619 Referer: https://lustre.bandcamp.com/album/another-time-another-place-chapter-one Sec-Fetch-Dest: audio Sec-Fetch-Mode: no-cors Sec-Fetch-Site: cross-site User-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: 1584762263 t: 5bc9c67fe19303967d4cd011b59ff2003c407e39 token: 1584762263_4f450e24db979391dc6dfa1b2eaa0946e2880533
Response:
Accept-Ranges: bytesAccept-Ranges: bytes Age: 69682 Cache-Control: max-age=31536000 Content-Length: 2092804 Content-Range: bytes 6946816-9039619/9039620 Content-Type: audio/mpeg Date: Fri, 20 Mar 2020 03:50:00 GMT Last-Modified: Wed, 06 Feb 2019 23:36:57 GMT Via: 1.1 varnish Via: 1.1 varnish X-Cache: HIT, HIT X-Cache-Hits: 0, 0 X-Served-By: cache-mdw17382-MDW, cache-gru17151-GRU X-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