HTML5 Server-Sent Event - javascript

I am trying to build real time app using SSE.
But it doesn't work when I think I write everything in right way.
Please help me with this problem.
I know websockets is better than SSE but I in beginning
Here is my index.html code
<!DOCTYPE html>
<html>
<head>
<title>Using SSE(Server-sent event)</title>
<meta charset="utf-8">
</head>
<body>
<h1>Getting server updates</h1>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("getdata.php");
source.onmessage = function(event) {
console.log(JSON.parse(event.data));
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
and this is getdata.php page
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$pdo = new PDO("mysql:host=localhost;dbname=sse", 'root', 'secret');
$obj = $pdo->query("select * from users");
$arr = $obj->fetchAll();
echo "data: ".json_encode($arr);
flush();
?>
when i used
source.onerror = function(er){
console.log(er);
}
I got this
error { target: EventSource, isTrusted: true, currentTarget: EventSource, eventPhase: 2, bubbles: false, cancelable: false, defaultPrevented: false, composed: false, timeStamp: 5152.813223, cancelBubble: false, originalTarget: EventSource }
I tried comment code in html console.log(JSON.parse(event.data));
but it doesn't work too.
Please help understanding how SSE works and what is the wrong in my code?
Thanks in advance.

I found out it why it doesn't work.
I added \n\n
echo "data: ".json_encode($arr);
so it looks like this
echo "data: ".json.encode($arr)."\n\n";
I hope it helps

EDIT (just to leave in accordance for future viewers)
check (then press F12 in your browser and check "Console" - it's working for me in Firefox and Chrome)
See the code exactly as it are on that server:
sse.html
<!DOCTYPE html>
<html>
<head>
<title>Using SSE(Server-sent event)</title>
<meta charset="utf-8">
</head>
<body>
<h1>Getting server updates</h1>
<div id="result"></div>
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("getdata.php");
source.onmessage = function(event) {
console.log(JSON.parse(event.data));
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
getdata.php (still mysql, not msqli or PDO because of an old server)
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
include("../../admin2/config.inc.php");
connect_db();
$query = mysql_query( "select * from ttbb" ) or die( mysql_error() );
$arr = mysql_fetch_object( $query );
echo "data: ".json_encode($arr)."\n\n";
flush();
?>
print:

Firstly, and most importantly, the PHP script should be running forever, not doing one query and then dying. (If that was your intention, then you don't need a streaming solution, and should just use AJAX.)
Second, you need two LFs after each data::. And you (probably) also need ob_flush() in addition to just flush(). With all three changes it looks like this:
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$pdo = new PDO("mysql:host=localhost;dbname=sse", 'root', 'secret');
while(true){ //Deliberate infinite loop
$obj = $pdo->query("select * from users");
$arr = $obj->fetchAll();
echo "data: ".json_encode($arr)."\n\n";
#ob_flush();#flush(); //Use # to suppress v.rare but meaningless errors
sleep(1); //Poll the database every second.
}
?>
I've set it (the server) to poll the local database every second. You should adjust this based on the balance of server load against target latency.
IMPORTANT: This will send all user data to all clients, every second. You should redesign your SQL query to only fetch users that have changed since your last query. And then re-design the front-end to be given all users on the first call, and then after that just the changes.

Related

Output is empty when showing 4 rows of data and remove last row

I perform the event stream to stream data from the php script. I want to limit to 4 rows of data. Thus, i input the code to remove if the count is more than or equal to 4 rows. When I run the file, the output is empty but when I checked in the network tab, I could see the script continuously being executed.
Here is my code below..
html code
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
<h1>Getting server updates</h1>
<div id="result"></div>
<script>
const result = document.getElementById("result");
if (typeof(EventSource) !== "undefined") {
var source = new EventSource("randomData.php");
source.onmessage = function(event) {
//Redefine node at each message event
const node = document.createTextNode(event.data + "\n");
if ($("#result p").length >= 4) {
$("#result p:last").remove();
}
result.insertBefore("<p>"+node+"</p>", result.firstChild);
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
php code
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$countryarr = array("UNITED STATES", "INDIA", "SINGAPORE","MALAYSIA","COLOMBIA","THAILAND","ALGERIA","ENGLAND","CANADA","CHINA", "SAUDI ARABIA");
$length = sizeof($countryarr)-1;
$random = rand(0,$length);
$random1 = rand(0,$length);
$random_srccountry = $countryarr[$random];
$random_dstcountry = $countryarr[$random1];
echo "data: [X] NEW ATTACK: FROM [".$random_srccountry."] TO [".$random_dstcountry."] \n\n";
flush();
?>
What is the cause of the empty output??
Please help me correct the error and also I want to see the output. thank you...

Updating a webpage with server sent events in PHP

Hi I'm currently working on a personal project which has two components. I want to POST "baby, 1" to my server, and when my server receives that "baby, 1", I want to change the webpage to reflect the date (currently using the date to test). I'm currently using Postman to test and largely borrowing code from W3Schools.
testpage.php
<html lang ="en">
<head>
<meta charset ="UTF-8">
<title>Title</title>
</head>
<body>
<div id = "result"></div>
<script>
if (typeof(EventSource) !== "undefined")
{
var source = new EventSource("server.php");
document.getElementById("result").innerHTML+="thug";
source.onmessage = function (event) {
document.getElementById("result").innerHTML += event.data + "<br>";
};
}else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
</body>
</html>
server.php
<?php
$bool = "";
if($_SERVER["REQUEST_METHOD"] == "POST") {
if (!empty($_POST["baby"])) {
$bool = $_POST["baby"];
if ($bool == 1) {
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
}
}
}
?>
When I test with the w3schools default code
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$time = date('r');
echo "data: The server time is: {$time}\n\n";
flush();
?>
testpage.php updates properly. When I try to POST to server.php with (baby,1) testpage.php does not update. I am really struggling to figure out why this is happening.

How to see errors about server sent events?

I coded a website using HTML5 Server Sent Events and it's working like charm on Godaddy shared hosting, however the same site with exactly the same code isn't working on 101domain shared hosting.
Rest all is working fine, except chat functionality using Server Sent Events.
How to find the errors in the script.
Here is the HTML page, with SSE javascript code.
<?php
$get_value_this_url = "globalchat";
?>
<div id="chat">
<div id="chats-div">
<p id="tip">(tip! kickstart a discussion by sharing this page)</p>
<ul id="chats-ul">
<?php
/*This session id will be used to fetch the latest chat via SSE*/
$_SESSION["id"] = 1;
if($stmt = $con->prepare("SELECT `icicinbbcts_id`, `icicinbbcts_user`, `icicinbbcts_chats` FROM `icicinbbcts_chats` WHERE `icicinbbcts_video_id` = ? ORDER BY `icicinbbcts_id` DESC LIMIT 25")){
$stmt->bind_param("s", $video_id);
$video_id = $get_value_this_url;
if ($stmt->execute()) {
$stmt->bind_result($id, $user, $chats);
$stmt->store_result();
if($stmt->num_rows() > 0){
$_SESSION["offset"] = $stmt->num_rows;
}
while ($stmt->fetch()) {
//print_r($user .": ". $chats."<br>");
echo '<li class="chats"><span id="nicknameChats">'.$user.'</span>: '.$chats.'</li>';
//echo '<span class="line-spacing"></span>';
$_SESSION["offset"] = $stmt->num_rows;
if($_SESSION["id"] < $id){
$_SESSION["id"] = $id;
}
}
}else
echo $stmt->error;
}else
echo $stmt->error;
$stmt->free_result();
$stmt->close();
?>
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("auto_update.php?r=<?php echo $get_value_this_url; ?>");
source.onmessage = function(event) {
var obj = JSON.parse(event.data);
$("#chats-ul").append('<li class="chats"><span id="nicknameChats">'+obj.user+'</span>: '+obj.chats+'</li>');
$('#chats-ul').scrollTop($(window).height());
};
} else {
document.getElementById("chats-ul").innerHTML = "Your browser doesn't support a part of HTML5, so please use modern browsers like Chrome, Firefox, etc.";
}
</script>
</ul>
</div>
<input id="text-area" class="q" name="text-input" form="textForm" maxlength="140" placeholder="Type to comment" ></input>
</div>
And here's the server side PHP script.
<?php session_start(); ?>
<?php //error_reporting(E_ALL); ?>
<?php require "connection.php";?>
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
if($stmt = $con->prepare("SELECT `icicinbbcts_id`, `icicinbbcts_user`, `icicinbbcts_chats` FROM `icicinbbcts_chats` WHERE `icicinbbcts_video_id` = ? AND `icicinbbcts_id` > ? ORDER BY `icicinbbcts_id` DESC")){
$stmt->bind_param("si", $video_id, $row_id);
$row_id = $_SESSION["id"];
$video_id = mysqli_real_escape_string($con, strip_tags($_GET["r"]));
if ($stmt->execute()) {
$stmt->bind_result($id, $user, $chats);
$stmt->store_result();
if($stmt->num_rows > 0){
while ($row = $stmt->fetch()) {
if($_SESSION["id"] < $id){
$send = array("user" => $user, "chats" => $chats);
echo "retry: 100\n";
echo "data: ".json_encode($send)."\n\n";
ob_end_flush();
flush();
$_SESSION["id"] = $id;
}
}
}
}else
echo $stmt->error;
}else
echo $stmt->error;
$stmt->close();
?>
The same above code works perfectly on Godaddy shared hosting, however the save code just isn't working on 101domain.
I tried putting charset UTF-8 in both PHP and HTML, but that din't help, I tried adding ob_flush in server side PHP script and it din't help too.
There's nothing wrong with connection.php because same file on other pages works fine.
On chat functionality the chat messages are getting inserted into the database, however it's not showing on the page, unless we refresh the page.
How to check for errors and how to debug Server Sent Events?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
I did console.log and didn't find the log in chrome, when I placed console.log code at the point shown below in the code.
<script>
if(typeof(EventSource) !== "undefined") {
console.log("SSE is supported"); //placing console.log here, displays the message in chrome developer tool
var source = new EventSource("auto_update.php?r=<?php echo $get_value_this_url; ?>");
source.onmessage = function(event) {
console.log("message isn't received from server"); //placing console.log here doesn't display any log message in Chrome Developer Tool
var obj = JSON.parse(event.data);
$("#chats-ul").append('<li class="chats"><span id="nicknameChats">'+obj.user+'</span>: '+obj.chats+'</li>');
$('#chats-ul').scrollTop($(window).height());
};
} else {
document.getElementById("chats-ul").innerHTML = "Your browser doesn't support a part of HTML5, so please use modern browsers like Chrome, Firefox, etc.";
}
</script>
So from the console.log above, we see that the SSE script is not receiving messages from backend, and backend code is shown above, can you show what's wrong with the backend code?
Since the result it works with one provider but not another, it is probably a server configuration issue.
Here are some things you can try to narrow down the issue:
In the javascript script use console.log(event) to check if you are getting anything from the server
Check the network tab in the developer tools area of browsers (in Chrome choose other to view server sent events).
If there is no output then try narrowing the problem down on the server. Resolev SSE output early to see if SSE mechanism works. Bit by bit resolve the SSE later and later until it breaks. If there is a difference on a specific line between providers it may be due to the PHP version. To compare php versions run <?php phpinfo() ? in a php file.
If you find a difference contact your provider!
You want to report errors?
<?php
// Turn off error reporting
error_reporting(0);
// Report runtime errors
error_reporting(E_ERROR | E_WARNING | E_PARSE);
// Report all errors
error_reporting(E_ALL);
// Same as error_reporting(E_ALL);
ini_set("error_reporting", E_ALL);
// Report all errors except E_NOTICE
error_reporting(E_ALL & ~E_NOTICE);
?>

Executing php file from another php file

Can I trigger the execution of a php file from another php file when performing an action? More specific, I have an anchor generated with echo, that has href to a pdf file. In addition of downloading the pdf I want to insert some information into a table. Here's my code, that doesn't work:
require('./database_connection.php');
$query = "select author,title,link,book_id from book where category='".$_REQUEST['categorie']."'";
$result = mysql_query($query);
$result2 = mysql_query("select user_id from user where username='".$_REQUEST["username"]."'");
$row2 = mysql_fetch_row($result2);
while($row= mysql_fetch_row($result))
{
echo '<h4>'.$row[0].' - '.$row[1].'</h4>';
if(isset($_SESSION["username"]) && !empty($_SESSION["username"]))
{
echo '<input type="hidden" name="id_carte" value="'.$row[3].'">';
echo '<input type="hidden" name="id_user" value="'.$row2[0].'">';
echo ' <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script language="javascript">
function insert_download() {
$.ajax({
type: "GET",
url: "insert_download.php" ,
success : function() {
location.reload();
}
});
}
</script>
<a onclick="insert_download()" href="'.$row[2].'" download> download </a>';
}
And here's the insert_download.php:
<?php
require('./database_connection.php');
$query = "insert into download(user_id,book_id,date)values(".
$_REQUEST["id_carte"].",".
$_REQUEST["id_user"].",".
date("Y-m-d h:i:s").")";
mysql_query($query,$con);
mysql_close($con);
?>
Can anyone help me with this? Thanks!
As I understand correctly, you want to display a link, and when the user clicks that link,
some data is inserted into a database or something;
the user sees a download dialog, allowing him to download a file?
If this is correct, you can use this code:
On your webpage:
download
result.php:
<?php
$file = isset($_GET['file']) ? $_GET['file'] : "";
?>
<!DOCTYPE html>
<html>
<head>
<title>Downloading...</title>
<script type="text/javascript">
function redirect(url) {
//window.location.replace(url);
window.location.href = url;
}
</script>
</head>
<body>
Download is starting...
<script type="text/javascript">
redirect("http://example.com/download.php?file=dummy.pdf");
</script>
</body>
</html>
download.php:
<?php
$file = isset($_GET['file']) ? $_GET['file'] : "nullfile";
$file_url = "download_dir_or_something/".$file;
// Put some line in a log file...
file_put_contents("logfile.txt", "successful on ".date("Y-m-d H:i:s")."\n", FILE_APPEND);
// ...or anything else to execute, for example, inserting data into a database.
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"".basename($file_url)."\"");
readfile($file_url);
?>
Why not use a redirection instead of "complicated" AJAX?
<!-- in your first document -->
echo '<input type="hidden" name="id_carte" value="'.$row[3].'">';
echo '<input type="hidden" name="id_user" value="'.$row2[0].'">';
echo 'download';
and in download_pdf.php
<?php
require('./database_connection.php');
...
mysql_close($con);
header("location: " . $_GET['redirect']);
You're lacking basic skill of debugging. If I was you, I should:
Use a browser which supporting, ex: Chrome with "Network" inspecting tab ready
Try click on the link <a onclick="insert_download()" ... and see if the ajax request is performed properly (via Network inspecting tab from your chrome). If not, re-check the generated js, otherwise, something wrong with the download_pdf.php, follow next step
Inspecting download_pdf.php: turn on error reporting on the beginning (put error_reporting(E_ALL); and ini_set('display_errors', 1); on top of your file) try echoing something before and/or after any line you suspect that lead to bugs. Then you can see those ajax response from your Network inspecting tab... By doing so, you're going to narrow down which line/scope of code is causing the problem.
Note that the "echoing" trick can be avoid if you have a solid IDE which is supporting debugger.
Hope it can help

Server Sent Events : Not working

I am using HTML5 Server-Sent Events.
Actually I need to show notification (new record enter and which are unread) that's when any new record is insert in database (php/mysql).
So for testing purpose I just tried with count of total row. But I am getting this error message in my local-host:
Firefox can't establish a connection to the server at http://localhost/project/folder/servevent/demo_sse.php.
The line is:
var source = new EventSource("demo_sse.php");
I have tried this:
index.php
<script>
if(typeof(EventSource) !== "undefined") {
var source = new EventSource("demo_sse.php");
source.onmessage = function(event) {
document.getElementById("result").innerHTML = event.data;
};
} else {
document.getElementById("result").innerHTML = "Sorry, your browser does not support server-sent events...";
}
</script>
<div id="result"></div>
demo_sse.php
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
$db = mysql_connect("localhost", "root", ""); // your host, user, password
if(!$db) { echo mysql_error(); }
$select_db = mysql_select_db("testdatase"); // database name
if(!$select_db) { echo mysql_error(); }
$time = " SELECT count( id ) AS ct FROM `product` ";
$result = mysql_query($time);
$resa = mysql_fetch_assoc($result);
echo $resa['ct'];
flush();
?>
Please let me know what going wrong.
I know for notification we can use Ajax with some interval time, but I don't want such thing. As I have N number of records and which may slow my resources.
According to this,
There are several 'rules' that need to be met, and yours is lacking at this point:
Output the data to send (Always start with "data: ")
It is somehow like:
echo "data: {$resa['ct']}\n\n";
Setting a header to text/event-stream worked for me:
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
// Rest of PHP code
Please modify the following code snippet according to your requirements
<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
// infinite loop
while (1) {
// output the current timestamp; REPLACE WITH YOUR FUNCTIONALITY
$time = date('r');
echo "data: Server time: {$time}\n\n"; // 2 new line characters
ob_end_flush();
flush();
sleep(2); // wait for 2 seconds
}
?>
I tested this code snippet myself; it's working for me. If you have any query, let me know.

Categories

Resources