sreyansjain
SSE chunks and compression - responses being sent but without gzip compression
Hi I am trying to use Server Sent Events.
I want to send chunked responses.
I am able to send them like so
conn
|> put_resp_header("cache-control", "no-cache")
|> put_resp_header("connection", "keep-alive")
|> put_resp_header("content-type", "text/event-stream;")
|> send_chunked(200)
|> chunk("This is some respsonse")
The responses are being sent, but without gzip compression.
How do i get responses to be sent with gzip compression?
I am using the latest phoenix with latest bandit.
Please advise.
PS If I don’t send chunked response, it gets compressed. For ex -
conn
|> put_resp_header("cache-control", "no-cache")
|> put_resp_header("connection", "keep-alive")
|> put_resp_header("content-type", "text/event-stream;")
|> text("This would get compressed")
Is some magic happening in the text/2 method?
Marked As Solved
sreyansjain
Got it to work.
We need to set the content-encoding to gzip
and then manually compress the responses like so
conn
|> put_resp_header("cache-control", "no-cache")
|> put_resp_header("connection", "keep-alive")
|> put_resp_header("content-type", "text/event-stream;")
|> put_resp_header("content-encoding", "gzip")
|> send_chunked(200)
And then compress the message manually and send them
defp send_chunk(conn, message) do
message = :zlib.gzip(message)
{:ok, conn} =
conn
|> prepare_sse()
|> chunk(message)
conn
end
7
Also Liked
sreyansjain
SSE compression in long lived connection for streaming updates –
# lib/aet_web/controllers/sse_controller.ex
defmodule AetWeb.SseController do
use AetWeb, :controller
def stream(conn, _params) do
conn =
conn
|> put_resp_header("content-type", "text/event-stream")
|> put_resp_header("content-encoding", "gzip")
|> put_resp_header("cache-control", "no-cache")
# |> put_resp_header("connection", "keep-alive")
|> send_chunked(200)
# Initialize zlib compression context with gzip wrapper
z = :zlib.open()
:ok = :zlib.deflateInit(z, 9, :deflated, 31, 8, :default) # 31 = gzip format
# Subscribe to PubSub
Phoenix.PubSub.subscribe(Aet.PubSub, "events")
# Start streaming
try do
stream_events(conn, z)
after
# IO.puts("Finalizing stream...")
compressed_end = :zlib.deflate(z, "", :finish)
# IO.inspect(compressed_end, label: "Final chunk")
Plug.Conn.chunk(conn, compressed_end)
cleanup_zlib(z)
end
end
defp stream_events(conn, z) do
receive do
{:event, data} ->
# Compress incrementally with sync flush
compressed_chunk = :zlib.deflate(z, data, :sync) # :sync flushes immediately
case Plug.Conn.chunk(conn, compressed_chunk) do
{:ok, conn} ->
IO.puts("Chunk sent successfully")
stream_events(conn, z)
{:error, :closed} ->
IO.puts("Client disconnected")
conn # Cleanup handled in `after` clause
end
after
1000 -> # Timeout to prevent infinite loop if no events
IO.puts("No events received in 1s, continuing...")
stream_events(conn, z)
end
end
defp cleanup_zlib(z) do
IO.puts("Cleaning up zlib context...")
case :zlib.deflateEnd(z) do
:ok -> :zlib.close(z)
error ->
IO.inspect(error, label: "DeflateEnd error")
:zlib.close(z)
end
rescue
e ->
IO.inspect(e, label: "Cleanup error")
:zlib.close(z)
end
end
4
hubertlepicki
Last Post!
sreyansjain
SSE compression in long lived connection for streaming updates –
# lib/aet_web/controllers/sse_controller.ex
defmodule AetWeb.SseController do
use AetWeb, :controller
def stream(conn, _params) do
conn =
conn
|> put_resp_header("content-type", "text/event-stream")
|> put_resp_header("content-encoding", "gzip")
|> put_resp_header("cache-control", "no-cache")
# |> put_resp_header("connection", "keep-alive")
|> send_chunked(200)
# Initialize zlib compression context with gzip wrapper
z = :zlib.open()
:ok = :zlib.deflateInit(z, 9, :deflated, 31, 8, :default) # 31 = gzip format
# Subscribe to PubSub
Phoenix.PubSub.subscribe(Aet.PubSub, "events")
# Start streaming
try do
stream_events(conn, z)
after
# IO.puts("Finalizing stream...")
compressed_end = :zlib.deflate(z, "", :finish)
# IO.inspect(compressed_end, label: "Final chunk")
Plug.Conn.chunk(conn, compressed_end)
cleanup_zlib(z)
end
end
defp stream_events(conn, z) do
receive do
{:event, data} ->
# Compress incrementally with sync flush
compressed_chunk = :zlib.deflate(z, data, :sync) # :sync flushes immediately
case Plug.Conn.chunk(conn, compressed_chunk) do
{:ok, conn} ->
IO.puts("Chunk sent successfully")
stream_events(conn, z)
{:error, :closed} ->
IO.puts("Client disconnected")
conn # Cleanup handled in `after` clause
end
after
1000 -> # Timeout to prevent infinite loop if no events
IO.puts("No events received in 1s, continuing...")
stream_events(conn, z)
end
end
defp cleanup_zlib(z) do
IO.puts("Cleaning up zlib context...")
case :zlib.deflateEnd(z) do
:ok -> :zlib.close(z)
error ->
IO.inspect(error, label: "DeflateEnd error")
:zlib.close(z)
end
rescue
e ->
IO.inspect(e, label: "Cleanup error")
:zlib.close(z)
end
end
4
Popular in Questions
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
I’m not a pro in using Regex and can’t figure out why the following behaviour happens, especially if we take into account the difference ...
New
Hi,
I have to write a raw query for one of my project. But till now I have used ecto queries and don’t have much experience writing raw ...
New
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
I tried installing
elixir 1.11.2
erlang 23.3.4
via asdf in my zsh shell. Enabled the versions locally and globally.
When I list them ...
New
Hi!
Currently I want to submit a form by pressing the Enter key. However, since my input field is of type “textarea” this is just adds a...
New
Other popular topics
Hi!
In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir?
Searched the docs for ip address and the web, no good results.
Thanks!
New
Hello, how can I check the Phoenix version ?
Thanks !
New
Hi All,
I set a environment variables in dev.exs , like below code.
when i start server, how can i set the ${enable} value?
thanks.
d...
New
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
After calling mix ecto.create I get this error:
17:00:32.162 [error] GenServer #PID<0.412.0> terminating
** (Postgrex.Error) FATAL...
New
This post is an instruction guide to help you setup your Neovim for Elixir development from scratch. It includes general information on h...
New
Latest Phoenix Threads
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #hex
- #security









