Skip to content

Instantly share code, notes, and snippets.

@tlvenn
Forked from rbishop/README.md
Created October 29, 2016 10:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tlvenn/fc869a93aa32cf3c1c5f0e9e375401a8 to your computer and use it in GitHub Desktop.
Save tlvenn/fc869a93aa32cf3c1c5f0e9e375401a8 to your computer and use it in GitHub Desktop.
A super simple Elixir server for sending Server Sent Events to the browser.

Generate a new Elixir project using mix and add cowboy and plug as dependencies in mix.exs:

  defp deps do
    [
      {:cowboy, "~> 1.0.0"},
      {:plug, "~> 0.8.1"}
    ]
  end

Then add the sse.ex file below to lib/ and run the code with mix run --no-halt lib/sse.ex. Point your browser to http://localhost:4000 and you're done.

If you don't feel like writing your own EventSource JavaScript, you can use the example in index.html below that comes from Cowboy. Just create a priv/static directory inside of your project.

<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">
function ready() {
if (!!window.EventSource) {
setupEventSource();
} else {
document.getElementById('status').innerHTML =
"Sorry but your browser doesn't support the EventSource API";
}
}
function setupEventSource() {
var source = new EventSource('/sse');
source.addEventListener('message', function(event) {
addStatus("server sent the following: '" + event.data + "'");
}, false);
source.addEventListener('open', function(event) {
addStatus('eventsource connected.')
}, false);
source.addEventListener('error', function(event) {
if (event.eventPhase == EventSource.CLOSED) {
addStatus('eventsource was closed.')
}
}, false);
}
function addStatus(text) {
var date = new Date();
document.getElementById('status').innerHTML
= document.getElementById('status').innerHTML
+ date + ": " + text + "<br/>";
}
</script>
</head>
<body onload="ready();">
Hi!
<div id="status"></div>
</body>
</html>
defmodule Sse do
import Plug.Conn
use Plug.Router
plug :match
plug :dispatch
get "/" do
conn
|> put_resp_header("content-type", "text/html")
|> send_file(200, "priv/static/index.html")
end
get "/sse" do
conn = put_resp_header(conn, "content-type", "text/event-stream")
conn = send_chunked(conn, 200)
send_message(conn, "Look, Ma'! I'm streaming!")
:timer.sleep(1000)
send_message(conn, "It only took two lines of code!")
:timer.sleep(1000)
send_message(conn, "All you have to do is set a header and chunk the response!")
:timer.sleep(1000)
send_message(conn, "Bye now!")
conn
end
defp send_message(conn, message) do
chunk(conn, "event: \"message\"\n\ndata: {\"message\": \"#{message}\"}\n\n")
end
end
# Run with mix run --no-halt lib/sse.ex
Plug.Adapters.Cowboy.http Sse, [], port: 4000
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment