elixir-plug / plug

Compose web applications with functions
https://hex.pm/packages/plug
Other
2.81k stars 578 forks source link

Plug.Conn is not closed when user closes the browser's tab (SSE) #1216

Closed mickel8 closed 2 months ago

mickel8 commented 2 months ago

Hi, I have implemented SSE (Server-Sent-Events) using Plug and they work really cool until a user closes browser's tab. For some reason, my Plug.Conn isn't notified/invalidated and I can still send data (although it doesn't appear in Wireshark). How can I detect that the user has closed the tab and stop the loop? The code looks more or less like this:

  get "/api/resource/:resource_id/sse/event-stream" do
    viewers = PeerConnection.get_all_running() |> length()

    {:ok, conn} =
      conn
      |> put_resp_header("content-type", "text/event-stream")
      |> put_resp_header("cache-control", "no-cache")
      |> send_chunked(200)
      |> chunk("data: {\"viewerscount\": #{viewers}}\n\n")

    update_viewers_count(conn, self())
  end

  defp update_viewers_count(conn, pid) do
    viewers = PeerConnection.get_all_running() |> length()
    Process.send_after(self(), :update_viewerscount, @viewers_count_update_interval)

    receive do
      :update_viewerscount ->
        {:ok, conn} = chunk(conn, "data: {\"viewerscount\": #{viewers}}\n\n")
        update_viewers_count(conn, pid)
    end
  end
josevalim commented 2 months ago

You should consult the underlying web server. In particular, I would expect the process to be killed (unless you are trapping exits, which then means you should handle the exit message accordingly).

mickel8 commented 2 months ago

Thanks! This is indeed a problem with a Bandit, or at least, when I switched to the cowboy, everything works as expected. I have moved the issue to mtrudel/bandit#344