https://linuxconfig.org/how-to-use-html5-server-sent-events
After setting up the html headers, we just used the
Finally in Lines 9-11, we sent our response to the client: the
It's even possible to break the response message on multiple lines: in this case each line, as said before, must start with "data:" and must be followed by a single newline character. The additional newline is required only on the last line.
The server can also control how often the client should try to reconnect (default is
After sending our response we called the
Objective
After reading this tutorial you should be able to understand and take advantage of HTML5 server-sent events.Requirements
- No particular requirements needed
Difficulty
EASYConventions
- # - requires given linux command to be executed with root privileges either directly as a root user or by use of
sudo
command - $ - given linux command to be executed as a regular non-privileged user
Introduction
Server-sent events is anHTML5
technology which allows a client to automatically monitor event
notifications from a server, and react as needed. This technology is
very useful to notify live events, to implement, for example, a live
messaging application or a news feed. In this tutorial we will see how
to implement this technology using PHP and javascript. A simple example
For the sake of this tutorial, we will work with a list of "animals" that will be displayed in a simple html page. While in a real-world application the data would have been stored and retrieved from a database, in this case, for simplicity, we will use a php array. What we want to obtain is a real-time notification of the changes in the animal list, so that we can update our html page accordingly, without having to refresh it.The Server side code
To begin with, let's populate our little array of animals in theanimals.php
file (we are working in the root directory of our web server VirtualHost):
$animals = ["cat", "dog", "cow", "zebra", "snake"];
Save and close the file as animals.php
.
Now, for the most important part: we have to write the script which
will emit the message that will be lately used by our client-side
javascript code. With a lot of fantasy we will name the script script.php
. The code is very simple, here it is:
header("Cache-Control: no-cache");
header("Content-Type: text/event-stream");
// Require the file which contains the $animals array
require_once "animals.php";
// Encode the php array in json format to include it in the response
$animals = json_encode($animals);
echo "data: $animals" . "\n\n";
flush();
The first thing to notice here is that we called the header
function in Lines 2-3: this is a function used to send raw http headers
. In this case we call it two times: the first in Lines 2 to setup the Cache-control
header field and specify caching directives (no page caching), the second in Lines 3, to set the Content-Type
to text/event-stream
. Those headers setup is necessary for our script to work correctly. It's also important to notice that to work correctly, the header
function must always be called before any other output is created. After setting up the html headers, we just used the
require_once
statement in Lines 6 to require the content of the animals.php
file, which contains the array we wrote before. In a real-case scenario, this would have been replaced by a SQL query
to retrieve such information from a database. Finally in Lines 9-11, we sent our response to the client: the
json-encoded
"animals" array. A very important thing to notice: Server Side Events
format requires each response sent by the server to be prefixed by the data:
string and followed by two newline characters
. In this case we used the \n
newline character because we are running on a unix-like platform; to
ensure cross-platform compatibility we would have used the PHP_EOL
constant. It's even possible to break the response message on multiple lines: in this case each line, as said before, must start with "data:" and must be followed by a single newline character. The additional newline is required only on the last line.
The server can also control how often the client should try to reconnect (default is
3
seconds), and the name of the event
(default is "message") sent to the client. To customize the former, we must use the retry
directive followed by the desired interval of time, expressed in milliseconds. For example, to setup an interval of 1 second: echo "retry: 1000\n";Notice that even here, a trailing newline is required. To change the event name, instead, we must use the
event
directive: echo "event: customevent\n";The default event is "message": this is important because the event must be specified in the client javascript code when adding the event listener, as we will see in a moment.
After sending our response we called the
flush
function: this is needed to ouput the data to the client. Client side code
First thing we are going to do client side is to prepare our html file with the list of available animals:
<html>
<body>
<ul id="availableAnimals">
<li></li>
</ul>
<script src="/script.js"></script>
</body>
</html>
This is really some basic html with a little bit of php to
display the list of animals at the moment of the page loading and to
include our .js file (script.js), but will server our purpose. Now,
let's see how actually we can use Server side events. The first thing we
have to do is to instantiate an Event source object
. In our javascript file, write: let eventSource = new EventSource('script.php');
As you can see, we passed the path to our server script as an argument in the EventSource
object constructor. This object will open a connection to the server. Now, we must add an event listener
, so that we can perform some actions when a message is received from the server: let eventSource = new EventSource('script.php');
eventSource.addEventListener("message", function(event) {
let data = JSON.parse(event.data);
let listElements = document.getElementsByTagName("li");
for (let i = 0; i < listElements.length; i++) {
let animal = listElements[i].textContent;
if (!data.includes(animal)) {
listElements[i].style.color = "red";
}
}
});
When a message is received, we use the
As you can see, as soon as the "cat" is removed from the "animals" array (our source of data) the element displayed in the html page is modified, to reflect that change.
The stream of data between the server and the client can be interrupted by using the
JSON.parse
method in Line 4 to
transform the data sent by the server (a string, contained in the
data
property of the event object), into a javascript array. After that we loop in Lines 7-11 through all the elements with the
tag, which are the elements of our list of animals: if some element
does not appear to be anymore in the array sent by the server, the color
of the text contained in the list is changed to red, because the
"animal" is no longer available (a better solution would have been to
only include the changed or missing element name in the server response,
but our purpose here is just to demonstrate how the technology works).
The change in the page will happen in real time, so no need to refresh.
You can observe how our page takes advantage of server sent events, in
the video below: As you can see, as soon as the "cat" is removed from the "animals" array (our source of data) the element displayed in the html page is modified, to reflect that change.
The stream of data between the server and the client can be interrupted by using the
close
method of the eventSource
object: eventSource.close()To handle connection
open
, and error
events, dedicated event listeners can be added to the object.
No comments:
Post a Comment