sreyansjain
Server Sent Events - https does not work: net::ERR_HTTP2_PROTOCOL_ERROR
Hello,
I am trying to get server sent events to work with Phoenix. And I can get it to work successfully over http.
Following are the steps i followed -
Add mime type to config.exs
config :mime, :types, %{
"text/event-stream" => ["sse"]
}
In my controller I have
defmodule MyAppWeb.NotificationController do
use MyAppWeb, :controller
# alias Phoenix.PubSub
def index(conn, _params) do
conn =
conn
|> put_resp_header("Cache-Control", "no-cache")
|> put_resp_header("connection", "keep-alive")
|> put_resp_header("Content-Type", "text/event-stream; charset=utf-8")
|> put_resp_header("Access-Control-Allow-Origin", "*")
|> send_chunked(200)
IO.puts("===============")
PubSub.subscribe(
self(),
:notification
)
|> IO.inspect()
IO.puts("===============")
IO.inspect(self())
sse_loop(conn, self())
end
defp sse_loop(conn, pid) do
# receive is what stops the router from processing
# and waits for an event to come in
receive do
# Send updates when :cagg is finished.
{:notification, :done} ->
# Fetch notification
IO.inspect("*************************")
# Send update.
chunk(conn, "data: message\n\n")
# Wait for next publish.
sse_loop(conn, pid)
# Stop SSE if this conn is actually down.
# Ignore other processes finishing.
# Notice the "^" in front of pid.
{:DOWN, _reference, :process, ^pid, _type} ->
nil
# Don't stop SSE because of unrelated events.
other ->
sse_loop(conn, pid)
end
end
end
In the router I have
get "/notification", NotificationController, :index
Also need to set idle_timeout for cowboy to infinity otherwise it times out after 60secs
So in the dev.exs file I have
http: [port: 8066, compress: true, protocol_options: [idle_timeout: :infinity]],
https: [
port: 8077,
compress: true,
cipher_suite: :strong,
keyfile: "priv/keys/localhost.key",
certfile: "priv/keys/localhost.cert",
protocol_options: [idle_timeout: :infinity]
],
In the template I have simple javascript for SSE
<script>
let eventSource = new EventSource("/notification");
eventSource.onmessage = function(event) {
console.log("New message", event.data);
};
</script>
I got great help from this blog - Server Sent Events with Elixir
Everything works over http. However for https it doesn’t work.
I get this error
GET https://localhost:8077/notification net::ERR_HTTP2_PROTOCOL_ERROR
Request your kind help.
Marked As Solved
sreyansjain
Whole thing works well over https when I use a real domain and a valid certificate. The issue seems to be there only with localhost.
I am still trying to figure out how to make it work over localhost using https.
Also Liked
vfsoraki
For local certificates, I use makecert to generate valid certificates for local domains. I am on Linux, but this or similar tools should be available for other OSes.
I then add my local domains to /etc/hosts and I also have a local Nginx configured to serve my local projects using their respective local domains.
Should be easy to set up. If you’re having a problem, reply here.
Exadra37
Phoenix has a built-in tool for this:
mix phx.gen.cert
Check instructions at config/dev.exs:
# ## SSL Support
#
# In order to use HTTPS in development, a self-signed
# certificate can be generated by running the following
# Mix task:
#
# mix phx.gen.cert
#
# Note that this task requires Erlang/OTP 20 or later.
# Run `mix help phx.gen.cert` for more information.
#
# The `http:` config above can be replaced with:
#
# https: [
# port: 4001,
# cipher_suite: :strong,
# keyfile: "priv/cert/selfsigned_key.pem",
# certfile: "priv/cert/selfsigned.pem"
# ],
#
# If desired, both `http:` and `https:` keys can be
# configured to run both http and https servers on
# different ports.
vfsoraki
You’re free to not use example.com. I don’t use it. I use a TLD of my own, and I don’t have any problems since that TLD will never exist in the outer world.







