Search code examples
javascriptphpmysqlserver-sent-eventseventsource

Getting response of mysql select with SSE


I am attempting to use EventSource to create a live connection chat 1 to 1. I have my event source set up and from what developer tools is telling me, it is open and working however the response data is not being displayed from the PHP file.

PHP:

<?php
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');

session_start(); // Starting Session
include 'dbconnect.php';
include 'Session.php';

$messageuserid = $_GET['messageuserid'];

$RunSqlGM = "SELECT * FROM messages WHERE (SUsername = '$Session_Username' AND RUsername = '$messageuserid') OR (SUsername = '$messageuserid' AND RUsername = '$Session_Username')";
$getmessagethread = mysqli_query($con,$RunSqlGM)or die(mysqli_error());

while($MessageRows = mysqli_fetch_array($getmessagethread)) {
    $MSUsername = $MessageRows['SUsername'];
    $MRUsername = $MessageRows['RUsername'];
    $MSender = $MessageRows['Sender'];
    $MessageContent = $MessageRows['Message'];
    $TimeStamp = date("g:ia \o\\n l jS F Y", strtotime($MessageRows["Time"]));


    if ($MSender === $Session_Username) {
        echo "<table class='messagebubbleright'>";
            echo "<tr><th></th></tr>";
            echo "<tr>";
                echo "<td class='inforight'>$MSender<br>$TimeStamp</td>";
            echo "</tr>";
            echo "<tr>";
                echo "<td class='bubbleright'>$MessageContent</td>";
            echo "</tr>";
        echo "</table>";
        flush();
    } else {
        echo "<table class='messagebubbleleft'>";
            echo "<tr><th></th></tr>";
            echo "<tr>";
                echo "<td class='infoleft'>$MSender<br>$TimeStamp</td>";
            echo "</tr>";
            echo "<tr>";
                echo "<td class='bubbleleft'>$MessageContent</td>";
            echo "</tr>";
        echo "</table>";
        flush();
    }
}
mysqli_close($con); // Connection Closed
?>

And the js that calls the event source is contained in this function which is started with a button click.

JS:

function GetMessages(GetMUserID) {
    if (typeof(EventSource) !== "undefined") {
        var source = new EventSource("db/getmessages.php?messageuserid=" + GetMUserID);
        source.addEventListener("open", function() {
            $("#readmessagearea").html("Getting server updates");
        });

        source.addEventListener("message", function(event) {
            $("#readmessagearea").html(event.data);
        });

    } else {
        $("#readmessagearea").html("Sorry, your browser does not support server-sent events...");
    }
}

Any help or guidance would be greatly appreciated. I am relatively new to SSE but from what I can see this should work.


Solution

  • There are a couple of problems with your PHP code. The easy to fix one is that it is best to change flush() into @ob_flush();@flush(). The ob_flush() makes sure PHP is not buffering anything, and the @ signs just make sure you don't get a warning message if buffering is not being used.

    The second problem is that the SSE protocol is minimal, but not that minimal! You need to prefix the message with "data:", and suffix it with "\n\n". Your HTML is not including any line feeds of its own, so I think it will work. (Unless there are line feeds in $MessageContent or any of the other dynamic data... I'd recommend some data filtering of not just carriage-returns, but also HTML tags, as your current code is vulnerable to embedded HTML attacks.)

    Another Approach: An alternative would be to send just a JSON object, containing $MessageRows["Time"], $MSender, $MessageContent, etc. and have the JavaScript client create the HTML. This is more flexible (e.g. clients in different countries can then have their own datestamp format, layouts can be changed, etc. without needing to touch the back-end), but moves more work to the front-end.